/*******************************************************************
This file is part of iAgenda.

iAgenda is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

iAgenda is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with iAgenda.  If not, see <http://www.gnu.org/licenses/>.
*******************************************************************/

// iAgenda.cpp : Defines the entry point for the application.
//
#include <windows.h>
#include <regext.h>
#include <snapi.h>
#include <vector>

#include "iAgenda.h"
#include "Skin.h"
#include "ListData.h"
#include "ListDataPoom.h"
#include "GraphicFunctions.h"
#include "FileUtils.h"
#include "RegistryUtils.h"
#include "Sensor.h"
#include "Titlebar.h"
#include "Version.h"
// for EDB
#include <windbase.h>

//#include "regext.h"
//#include "snapi.h"

//#define DEBUG_GRAPHICS_SPEED
#define ELLIPSIS ((TCHAR)0x2026)

//-----------------------------------------------------------------------------
// Global data
//
HINSTANCE   hInst;                     // Program instance handle
extern bool bSet; //ajige 4/1/10 //TODO is this causing problems??????
CSettings * pSettings = NULL;

int         nCurrentTab = 2;
int         nHighlightedTab = 2;
		//bool        isRecentsTainted = false;  //todo: check this
bool        isPoomTainted = false;
		//ajige bool        isFavoritesTainted = false;

TCHAR       szWindowTitle[64] = {0};
//5/5/10bool        hasiDialerServices = false;

#define HR_NOTIFY_COUNT 3
HREGNOTIFY  hrNotify[HR_NOTIFY_COUNT] = {0};

// Information about which screen you're on
HistoryItem History[3];
int         depth = 0;

int		    ListHeight = 0;
int         AverageItemHeight = DEFAULT_ITEM_HEIGHT;
std::vector<int> vStartPosition;
int         GroupPosition[ALPHABET_MAX_SIZE];
POINT       ptMouseDown = { -1, -1 };

// Graphic
int         scale = 1;
RECT		rScreen = {0};
int         nScreenHeight = 0;
RECT        rTitlebar = {0};
RECT        rServiceTitle = {0};
RECT        rHeader = {0};
RECT		rMenubar = {0};
RECT		rList = {0};
RECT        rContent = {0};
RECT        rClickRegion = {0};
int         rListHeight = 0;
int         minScrolled = 0;
int         maxScrolled = 0;

// Fonts
HFONT       TitlebarFont;
HFONT		MainListFont;
HFONT		PrimaryListFont;
HFONT		SecondaryListFont;
HFONT		GroupFont;
HFONT		ItemDetailsFont;
HFONT		ListIndicatorFont;
HFONT		KeyboardFont;

// Screen buffers
HDC         hdcMem = NULL;
HBITMAP		hbmMem = NULL;
HDC         hdcTmp = NULL;
HBITMAP		hbmTmp = NULL;
HDC			hdcSkin = NULL;
HBITMAP		hbmSkin = NULL;
HDC         hdcPage1 = NULL;
HBITMAP     hbmPage1 = NULL;
HDC         hdcPage2 = NULL;
HBITMAP     hbmPage2 = NULL;
HDC         hdcCanvas = NULL;
HBITMAP     hbmCanvas = NULL;

// Scrolling
bool        bMouseDown = false;
bool		bDragging = false;
bool		bScrolling = false;
int			LastX;
int			LastY;
int			tStartTime;
int			tEndTime;
double		Velocity = 0;
int         nKeyRepeatCount = 0;
int			iSwipeDir=1; //4/8/10 some prefer reverse swipe
// G Sensor Scrolling
bool        bGScrolling = false;
UINT        iInitialAngle = 0;


// Scroll To
DWORD       Scroll_StartTime = 0;
double		Scroll_TimeCounter = 0.0;
int 		Scroll_StartPosition = 0;
int 		Scroll_Change = 0;
double		Scroll_Duration = 0.0;

// Screen Transition
DWORD       dwTransitionStart = 0;
double      dTransitionPct = 0.0;
int         nTransitionDuration = 0;
bool        bTransitioning = false;
TransitionType trTransitionType = ttSlideLeft;
bool        bBackOnDeactivate = false;
//TransitionType trTransitionType = ttExpand;

// Popup window
bool        bDisplayingPopup = false;
PopupType   ptPopupType = ptKeyboard;


//4/15/10 for edit
// These deal with an expanded item (to choose from a list, for instance)
//int         nExpandedIndex = -1;
//int         rExpandedHeight = 0;
//int         nQueuedExpandedIndex = -1;
//TCHAR       EditOptions[MAX_OPTIONS][MAX_LOADSTRING];
//int         nOptions;
//bool		bExpanded=false;
//int iLine=0; //4/30/10
//RECT        rTouchZone = {0};//5/2/10

DataItem dItem; //5/2/10


// Keyboard Rows/Columns
TCHAR       alphabet[ALPHABET_MAX_SIZE];
int         nKeyboardLetters = 26;
int         nKeyboardRows = 0;
int         nKeyboardCols = 0;
int		    GroupWidth = 0;     // Keyboard group width
int		    GroupHeight = 0;    // Keyboard group height
struct Group	//ajige for calendar popup, TODO: redo to use old keyboard code instead
{
	int			ID;
	RECT		Rect;
	int			Color; //ajige 4/27/10 to mark dates in calendar with appointments
	//int 			Day;  //ajige added then removed
};

struct Group	GroupArray[49];		// ajige changed from 30 to 49 (7*7)Group references to ListData[] items

SYSTEMTIME stToday; //ajige extern declared in other units that use it

// Message dispatch table for MainWindowProc
const struct decodeUINT MainMessages[] = {
    WM_PAINT,        DoPaintMain,
    WM_DESTROY,      DoDestroyMain,
    WM_ACTIVATE,     DoActivate,
    WM_SIZE,         DoSize,
    WM_LBUTTONDOWN,  DoMouseDown,
    WM_MOUSEMOVE,    DoMouseMove,
    WM_LBUTTONUP,    DoMouseUp,
    WM_TIMER,        DoTimer,
    WM_KEYDOWN,      DoKeyDown,
    WM_COMMAND,      DoCommand,
    WM_TITLEBAR,     DoTitlebarCallback,
    WM_SETTINGS_TAINTED, DoSettingsTaintedCallback,
		//    WM_RECENTS_TAINTED, DoRecentsTaintedCallback,
	WM_HTC_GESTURE,	DoGestureCallback,
	WM_HTC_TOUCH, DoTouchCallback,
    PIM_ITEM_CREATED_LOCAL, DoPoomTaintedCallback,
    PIM_ITEM_DELETED_LOCAL, DoPoomTaintedCallback,
    PIM_ITEM_CHANGED_LOCAL, DoPoomTaintedCallback,
    PIM_ITEM_CREATED_REMOTE, DoPoomTaintedCallback,
    PIM_ITEM_DELETED_REMOTE, DoPoomTaintedCallback,
    PIM_ITEM_CHANGED_REMOTE, DoPoomTaintedCallback,
};



// int	hgScreen: to indicate whether this is for tasks 1 or appointments 2 or both  0
// ajige: might be possible to remove this. Will see when I learn the code better.
// TCHAR * filename: filename of cache data file (NULL means don't cache)
// int parent: index of "parent" or "go back"
// bool hasMenus: whether the menus (tabs at bottom) should be displayed
// HRESULT fnPopulate(HANDLE fh): function reference for (re)populate
// HRESULT fnGetGroup(DataItem * data, TCHAR * buffer, int cchDest)
// HRESULT fnClick(DataItem * data, POINT pt, int * newScreen): function reference for click
// HRESULT fnAdd(void): function reference for add
// HRESULT fnToggleFavorite(DataItem * data): function reference for toggle favorite
// HRESULT fnGetHBitmap(DataItem * data, HBITMAP * phBitmap, UINT * puWidth, UINT * puHeight): function reference for get bitmap

const struct ScreenDefinition Screens[] = 
{
    // cached, All Appointments - 0
	0,
	NULL,//TEXT("allapps.dat"),
	3,
	true,
	PoomPopulate,
	PoomGetTitle,
	PoomGetGroup,
	PoomClick,
	PoomAddItem,
	NULL,
	NULL,


	// cached, "All Tasks" - 1
	1,
	NULL,//TEXT("alltasks.dat"), 
	3,
	true,
	PoomPopulate,
	PoomGetTitle,
	PoomGetGroup,
	PoomClick,
	PoomAddItem,
	NULL,
	NULL,

    // cached, "Agenda" - 2

	2,
	NULL,//TEXT("agenda.dat"),
	3,
	true,
	PoomPopulate,
	PoomGetTitle,
	PoomGetGroup,  // allelimo: group header for agenda tab, change this to PoomGetGroup
	PoomClick,
	NULL,  //ajige need to have option to add either task or app
	NULL,
	NULL,

    // uncached, categories - 3
	3,
    NULL,
    -1,
    true,
    PoomCategoriesPopulate,
    PoomCategoriesGetTitle,
    NULL,
    PoomCategoriesClick,
    NULL,
    NULL, 
    NULL,
//ajige: 4 and 5 has been combined, so that 5 can be deleted. I haven't done that,
//because I didn't know which other screens would be affected. Actually 5 will be used for edit
    // uncached, poom item details - 4
	4,//5/14 ajige 2,//appps&tasks
    NULL,
    0,//2,
    false,//ajige true: to display manage and edit as menus, stuck on bottom, then test for above to see that it's details screen
    PoomDetailsPopulate,
    PoomDetailsGetTitle,
	NULL, //PoomGetGroup, //4/15/10 NULL,
    EditClick,//PoomClick,	//PoomDetailsClick,//makes no difference if this or NULL
    NULL,
    NULL, //ajige PoomDetailsToggleFavorite,
    NULL, //PoomDetailsLoadBitmap,

	// uncached, poom2 item details - 5
	5,//5/14 ajige 1,//use for editing, the options hgScreen
	NULL, //filename 
	4,			//parent
	false, //has menus
	EditPopulate,
	EditGetTitle,
	NULL, //group
	//NULL,//
	NULL,//EditClick,//4/22/10 makes no difference if this or NULL
	NULL,//add
	NULL, //ajige PoomDetailsToggleFavorite,
	NULL, //Poom2DetailsLoadBitmap,

    // uncached, list of contacts in a category - 6
	//ajige: use for filtered list, or can it be incorporated into the screens above?
	6,
    NULL,
    3,
    true,
    PoomPopulate,
    PoomGetTitle,
    PoomGetGroup,
    PoomClick,
    PoomAddItem,
    NULL,
    NULL,
};
//4/16/10
// Configuration of the edit fillers
/* struct SingleEdit TaskEdits[] = 
 {
   //ajige3/31/10  

	//(TCHAR *)PIMPR_SUBJECT,//pSettings->subject_string,
     stEdit, 
    NULL,

	//(TCHAR *)PIMPR_IMPORTANCE,//pSettings->priority_string,
	stList,
	priorityFiller,
	
	//pSettings->status_string, =complete
    stOnOff,
    NULL,

	//(/TCHAR *)PIMPR_START,//pSettings->starts_string,
    stCalendar, 
    NULL,

	//(TCHAR *)PIMPR_DUE_DATE,//pSettings->duedate_string,
     stCalendar, 
    NULL,

	//pSettings->occurs_string, 
    stOnOff,
    NULL,

    //pSettings->reminder_string,
	stOnOff,
	NULL,

	//(TCHAR *)PIMPR_CATEGORIES,//pSettings->categories_string,
    stList,
    categoryFiller,

	//(TCHAR *)PIMPR_SENSITIVITY,//pSettings->sensitivity_string, 
    stList,
    sensitivityFiller,

    //(TCHAR *)PIMPR_BODY_TEXT,//pSettings->notes_string, 
    stEdit,
    NULL,
};*/

/* struct SingleEdit AppEdits[] = 
 {
   //ajige3/31/10  

	//(TCHAR *)PIMPR_SUBJECT,//pSettings->subject_string,
     stEdit, 
    NULL,

	//(TCHAR *)PIMPR_LOCATION,//pSettings->location_string,
	stEdit,
	NULL,

	//(/TCHAR *)PIMPR_START,//pSettings->starts_string,
    stCalendar, 
    NULL,

	//(TCHAR *)PIMPR_END,//pSettings->ends_string,
    stCalendar,
    NULL,

	//(TCHAR *)PIMPR_ALL_DAY_EVENT,//pSettings->allday_string,
	stOnOff,
	NULL,

	//pSettings->occurs_string, 
    stOnOff,
    NULL,

    //pSettings->reminder_string,
	stOnOff,
	NULL,

	 //(TCHAR *)PIMPR_CATEGORIES,//pSettings->categories_string,
    stList,
    categoryFiller,

	//pSettings->attendees_string, 
    stList,
    attendeeFiller,
	   
    //pSettings->status_string, 
    stList,
    statusFiller,	

    //(TCHAR *)PIMPR_SENSITIVITY,//pSettings->sensitivity_string, 
    stList,
    sensitivityFiller,

    //(TCHAR *)PIMPR_BODY_TEXT,//pSettings->notes_string, 
    stEdit,
    NULL,
};*/

//TCHAR EditValuesT[ARRAYSIZE(TaskEdits)][MAX_LOADSTRING] = {0};
//TCHAR EditValuesA[ARRAYSIZE(AppEdits)][MAX_LOADSTRING] = {0};
//4/16/10

//=============================================================================
//
// Program entry point
//
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPWSTR lpCmdLine, int nCmdShow) {
    MSG msg;
    HWND hwndMain;
	
	//allelimo todo: is this the best part of the app to get "today"? 
	//ajige: only to make sure it's visible everywhere
	GetLocalTime(&stToday); 
	
    // Initialize this instance.
    hwndMain = InitInstance(hInstance, lpCmdLine, nCmdShow);
    if (hwndMain == 0)
        return 0x10;

    // Application message loop
    while (GetMessage (&msg, NULL, 0, 0)) {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }
    // Instance cleanup
    return TermInstance (hInstance, msg.wParam);
}
//-----------------------------------------------------------------------------
// InitInstance - Instance initialization
//
HWND InitInstance (HINSTANCE hInstance, LPWSTR lpCmdLine, int nCmdShow){
    WNDCLASS wc;
    HWND hWnd;

    // Save program instance handle in global variable.
    hInst = hInstance;

#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
    // If Windows Mobile, allow only one instance of the application.
    hWnd = FindWindow (SZ_APP_NAME, NULL);
    if (hWnd) {
        SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));   
        ParseCommandLine(hWnd, lpCmdLine);
        return 0;
    }
#endif

    // Register application main window class.
    wc.style = 0;                             // Window style
    wc.lpfnWndProc = MainWndProc;             // Callback function
    wc.cbClsExtra = 0;                        // Extra class data
    wc.cbWndExtra = 0;                        // Extra window data
    wc.hInstance = hInstance;                 // Owner handle
    wc.hIcon = NULL;                          // Application icon
    wc.hCursor = LoadCursor (NULL, IDC_ARROW);// Default cursor
    wc.hbrBackground = NULL;                  // No need to erase
	wc.lpszMenuName =  NULL;                  // Menu name
    wc.lpszClassName = SZ_APP_NAME;           // Window class name

    if (RegisterClass (&wc) == 0) return 0;
    // Create main window.
    hWnd = CreateWindowEx(WS_EX_NODRAG,       // Ex Style
                         SZ_APP_NAME,         // Window class
                         SZ_APP_NAME,         // Window title
                         WS_SYSMENU,          // Style flags
                                              // don't use WS_VISIBLE.
                                              // Why not? It causes an "error report"
                                              // Why? I don't know.
                         CW_USEDEFAULT,       // x position
                         CW_USEDEFAULT,       // y position
                         CW_USEDEFAULT,       // Initial width
                         CW_USEDEFAULT,       // Initial height
                         NULL,                // Parent
                         NULL,                // Menu, must be null
                         hInstance,           // Application instance
                         NULL);               // Pointer to create
                                              // parameters
    // Return fail code if window not created.
    if (!IsWindow (hWnd))
		return 0;

    // Initialize COM libraries (for POOM)
    if (FAILED(CoInitializeEx(NULL, 0)))
        return 0;

    // Get the window title (possibly, from iDialer)
	//5/5/10 not neccessary??
    //GetIDialerServiceName();
    //hasiDialerServices = HasMultipleIDialerServices();

    // Initialize Callbacks for detecting tainted data
    HRESULT hr = RegistryNotifyWindow(
        HKEY_CURRENT_USER, IDIALER_REG_KEY, SERVICE_NUM, 
        hWnd, WM_SETTINGS_TAINTED, SETTINGS_TAINTED_IDIALER,
        NULL, &hrNotify[0]);

	// Notify if skin changed (maybe from installing new skin .cab file)
	hr = RegistryNotifyWindow(
		HKEY_CURRENT_USER, SZ_IAGENDA_REG_KEY, INI_SKIN_KEY,
		hWnd, WM_SETTINGS_TAINTED, SETTINGS_TAINTED_SKIN,
		NULL, &hrNotify[1]);

	// Notify if language changed (maybe from installing new language .cab file)
	hr = RegistryNotifyWindow(
		HKEY_CURRENT_USER, SZ_IAGENDA_REG_KEY, INI_LANGUAGE_KEY,
		hWnd, WM_SETTINGS_TAINTED, SETTINGS_TAINTED_LANGUAGE,
		NULL, &hrNotify[2]);

	// Setup scaling. DPI must be an integer multiple of DEFAULT_DPI
	// in order for everything to work correctly.
	scale = int(DRA::LogPixelsX() / DEFAULT_DPI);

	// Create fonts
	TitlebarFont = BuildFont(SCALE(TITLEBAR_FONT_SIZE), FALSE, FALSE);
	MainListFont = BuildFont(SCALE(MAINLIST_FONT_SIZE), FALSE, FALSE);
	PrimaryListFont = BuildFont(SCALE(ITEM_FONT_SIZE), FALSE, FALSE);
	SecondaryListFont = BuildFont(SCALE(ITEM_SECONDARY_FONT_SIZE), TRUE, FALSE);
	ItemDetailsFont = BuildFont(SCALE(ITEM_DETAILS_FONT_SIZE), FALSE, FALSE);
	GroupFont = BuildFont(SCALE(GROUP_ITEM_FONT_SIZE), TRUE, FALSE);
	ListIndicatorFont = BuildFont(SCALE(LIST_INDICATOR_FONT_SIZE), TRUE, FALSE);
	KeyboardFont = BuildFont(SCALE(KEYBOARD_FONT_SIZE), TRUE, FALSE);

    // Load User Settings
    pSettings = new CSettings();

    // Initialize titlebar callbacks
	if (pSettings->doShowFullScreen)
		InitTitlebar(hWnd);
	
	// Initialize sensors
	if (pSettings->doEnableSensor) {
		SensorGestureInit(hWnd);
		SensorPollingInit();
	}

	//reverse direction for swiping left and right
	if (pSettings->doReverseSwipe)
		iSwipeDir=-1;

    // Initialize the screen and bitmaps
    InitSurface(hWnd);

#if DEBUG
	// If there's a command line option, do it now
	// Test command line with argument
	//bool handled = ParseCommandLine(hWnd, TEXT("-details -2147483488"));
	// Test command line with no argument
	//bool handled = ParseCommandLine(hWnd, TEXT("-search"));
	// Test invalid oid
	//bool handled = ParseCommandLine(hWnd, TEXT("-details 999"));
#endif
	bool handled = ParseCommandLine(hWnd, lpCmdLine);

	// Default action is to load "Agenda view"
	if (!handled) {
		//PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, 2);
		if(CompareString(LOCALE_NEUTRAL, NORM_IGNORECASE, pSettings->openingScreen, -1, pSettings->allappointments_string, -1) == CSTR_EQUAL)
				PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, 0);
		else if(CompareString(LOCALE_NEUTRAL, NORM_IGNORECASE, pSettings->openingScreen, -1, pSettings->alltasks_string, -1) == CSTR_EQUAL)
				PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, 1);
		else if(CompareString(LOCALE_NEUTRAL, NORM_IGNORECASE, pSettings->openingScreen, -1, pSettings->agenda_string, -1) == CSTR_EQUAL)
				PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, 2);
	}

    // Standard show and update calls
    ShowWindow (hWnd, nCmdShow);
    UpdateWindow (hWnd);

    return hWnd;
}

//-----------------------------------------------------------------------------
// TermInstance - Program cleanup
//
int TermInstance (HINSTANCE hInstance, int nDefRC) {

    return nDefRC;
}
//=============================================================================
// Message handling procedures for MainWindow
//

//-----------------------------------------------------------------------------
// MainWndProc - Callback function for application window
//
LRESULT CALLBACK MainWndProc (HWND hWnd, UINT wMsg, WPARAM wParam, 
                              LPARAM lParam) {
    INT i;
    //
    // Search message list to see if we need to handle this
    // message. If in list, call procedure.
    //
    for (i = 0; i < ARRAYSIZE(MainMessages); i++) {
        if (wMsg == MainMessages[i].Code)
            return MainMessages[i].Fxn(hWnd, wMsg, wParam, lParam);
    }
    return DefWindowProc (hWnd, wMsg, wParam, lParam);
}

//-----------------------------------------------------------------------------
// DoPaintMain - Process WM_PAINT message for window.
//
LRESULT DoPaintMain (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {

    PAINTSTRUCT ps;
    RECT rect;
    HDC hdc;
    
    int rScreenWidth = rScreen.right - rScreen.left;
    int rScreenHeight = rScreen.bottom - rScreen.top;   

    hdc = BeginPaint (hWnd, &ps); 

    // rect is the region that needs to be painted
    rect = ps.rcPaint;

    if (bTransitioning) {
        RECT rContent = rScreen;

        if (trTransitionType == ttSlideRight 
            || trTransitionType == ttSlideLeft) 
		{

            rContent.top = rTitlebar.bottom;
            int rHeight = rContent.bottom - rContent.top;
            int width1 = (int)(rScreenWidth * dTransitionPct);
            int width2 = rScreenWidth - width1;

            if (trTransitionType == ttSlideLeft) 
			{
                BitBlt(hdcMem, rContent.left, rContent.top, width2, rHeight, 
                    hdcPage1, width1, rContent.top, SRCCOPY);

                BitBlt(hdcMem, width2, rContent.top, width1, rHeight,
                    hdcPage2, rContent.left, rContent.top, SRCCOPY);
            }
            else 
			{
                BitBlt(hdcMem, rContent.left, rContent.top, width1, rHeight, 
                    hdcPage2, width2, rContent.top, SRCCOPY);

                BitBlt(hdcMem, width1, rContent.top, width2, rHeight,
                    hdcPage1, rContent.left, rContent.top, SRCCOPY);
            }

            BitBlt(hdcMem, rTitlebar.left, rTitlebar.top, 
                rScreenWidth, rTitlebar.bottom - rTitlebar.top,
                hdcPage1, rTitlebar.left, rTitlebar.top, SRCCOPY);
        }//if (trTransitionType == ttSlideRight 

        else if (trTransitionType == ttKeyboardExpand 
            || trTransitionType == ttKeyboardShrink) 
		{

            double cubic = pow(dTransitionPct - 1, 3) + 1;
            if (trTransitionType == ttKeyboardShrink)
                cubic = 1 - cubic;

            int nKbWidth = (int)(rScreenWidth * cubic);
            int nKbHeight = (int)(rScreenHeight * cubic);

            BitBlt(hdcMem, rScreen.left, rScreen.top, 
                rScreenWidth, rScreenHeight, 
                hdcPage1, rScreen.left, rScreen.top, SRCCOPY);

            // for faster rendering, don't stretch or alpha-ize the keyboard
            if (pSettings->doFastGraphics) 
			{
                BitBlt(hdcMem, rScreen.right - nKbWidth, 
                    rScreen.bottom - nKbHeight, nKbWidth, nKbHeight,
                    hdcPage2, 0, 0, SRCCOPY);
            }
            else 
			{
                BltAlpha(hdcMem, rScreen.right - nKbWidth, 
                    rScreen.bottom - nKbHeight, nKbWidth, nKbHeight,
                    hdcPage2, 0, 0, rScreenWidth, rScreenHeight, 220);
            }
        }//else if (trTransitionType == ttKeyboardExpand
		else if (trTransitionType == ttEditExpand //5/3/10
            || trTransitionType == ttEditShrink) 
		{

            double cubic = pow(dTransitionPct - 1, 3) + 1;
            if (trTransitionType == ttEditShrink)
                cubic = 1 - cubic;

            int nKbWidth = (int)(rScreenWidth * cubic);
            int nKbHeight = (int)(rScreenHeight * cubic);

            BitBlt(hdcMem, rScreen.left, rScreen.top, 
                rScreenWidth, rScreenHeight, 
                hdcPage1, rScreen.left, rScreen.top, SRCCOPY);

            // for faster rendering, don't stretch or alpha-ize the keyboard
            if (pSettings->doFastGraphics) {
                BitBlt(hdcMem, rScreen.right - nKbWidth, 
                    rScreen.bottom - nKbHeight, nKbWidth, nKbHeight,
                    hdcPage2, 0, 0, SRCCOPY);
            }
            else {
                BltAlpha(hdcMem, rScreen.right - nKbWidth, 
                    rScreen.bottom - nKbHeight, nKbWidth, nKbHeight,
                    hdcPage2, 0, 0, rScreenWidth, rScreenHeight, 220);
            }
        }

        if (dTransitionPct == 1.0) 
		{
            bTransitioning = false;

            if (trTransitionType == ttSlideRight) {
                UnselectItem();
            }
			
			if (trTransitionType == ttKeyboardExpand 
				|| trTransitionType == ttKeyboardShrink) 
				bDisplayingPopup = trTransitionType == ttKeyboardExpand;
			else //5/3/10
				bDisplayingPopup = trTransitionType == ttEditExpand;

            KillTimer(hWnd, IDT_TIMER_TRANSITION);
            
            InvalidateRect(hWnd, &rScreen, FALSE);
        }

    }//if (bTransitioning)
	
    // not transitioning
    else 
	{
        DrawScreenOn(hdcMem, rect, hdcTmp, History[depth].scrolled);

        if (bDisplayingPopup) 
		{
            //switch (ptPopupType) 
			//{
             //   case ptKeyboard:
					// draw the keyboard
					//MessageBox(0,L"ptKeyboard",L"DoPainMain",0);
	                DrawKeyboardOn(hdcTmp, rScreen);  
                    BltAlpha(hdcMem, rScreen.left, rScreen.top,
                        rScreenWidth, rScreenHeight, hdcTmp, 0, 0, 
                        rScreenWidth, rScreenHeight, 220);
			/*		break;
				case ptEdit:
					//MessageBox(0,L"ptEdit",L"DoPainMain",0);
	                
					// draw the keyboard
	                DrawExpandOn(hdcTmp, rScreen,History[depth].scrolled);  
                    BltAlpha(hdcMem, rScreen.left, rScreen.top,
                        rScreenWidth, rScreenHeight, hdcTmp, 0, 0, 
                        rScreenWidth, rScreenHeight, 220);
                    break;
            }*/
        }
    }

    // Highlight the region being clicked right now
    if (GetCurrentItemIndex() > -1 || (bMouseDown && !bDragging 
        && (
            PtInRect(&rList, ptMouseDown)
            || PtInRect(&rHeader, ptMouseDown)
            || PtInRect(&rServiceTitle, ptMouseDown)// && hasiDialerServices  //5/5/10 not neccessary??
            || PtInRect(&rMenubar, ptMouseDown) 
                && !Screens[History[depth].screen].hasMenus
            )
        )) {
				//ExtTextOut(hdc,0,0,ETO_OPAQUE,&rect,NULL,0,NULL);
				//SelectObject(hdc, CreateSolidBrush(GetSkinRGB(SKIN_COLOR_HIGHLIGHT)));
				//SetBkColor(hdc, GetSkinRGB(SKIN_COLOR_HIGHLIGHT));
				//int padding = SCALE(ITEM_DETAILS_PADDING);
				//SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
				//rect.left=SCALE(64);//4/15/10 to avoid labels being inside the box.
				//if(!Screens[History[depth].screen].hasMenus)
					//rect.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;		
					//	RoundRect(hdc, 
					//		rect.left + padding / 2, 
					//		rect.top + padding / 3, 
					//		rect.right - padding / 2, 
					//		rect.bottom - padding / 3,
					//		padding, padding);
       DrawRect(hdcTmp, &rClickRegion, GetSkinRGB(SKIN_COLOR_HIGHLIGHT));

        BltAlpha(hdcMem, rClickRegion.left, rClickRegion.top, 
            rClickRegion.right - rClickRegion.left, 
            rClickRegion.bottom - rClickRegion.top,
            hdcTmp, rClickRegion.left, rClickRegion.top,
            rClickRegion.right - rClickRegion.left,
            rClickRegion.bottom - rClickRegion.top,
            128);
		//rect.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;
    }

    // Transfer everything to the actual screen
    BitBlt(hdc, rect.left, rect.top, rect.right - rect.left,
        rect.bottom - rect.top, hdcMem, rect.left, rect.top, SRCCOPY);

    EndPaint (hWnd, &ps);

    return 0;
}

//-----------------------------------------------------------------------------
// DoActivate - Process WM_ACTIVATE message for window
//
LRESULT DoActivate (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {

    DWORD dwState;
    RECT rc;

			//SYSTEMTIME stNow;
			//DATE dtNow;
			//DATE dtToday;
			//GetLocalTime(&stNow);
			//SystemTimeToVariantTime(&stToday,&dtToday);
			//SystemTimeToVariantTime(&stNow,&dtNow);
			//UINT iToday = (UINT)dtToday;
			//UINT iNow = (UINT)dtNow;
			//if (iToday != iNow && iNow !=0) 
			//{
			//	dtToday = dtNow;
			//	VariantTimeToSystemTime(dtNow, &stToday);
			//}
	

    if (wParam == WA_CLICKACTIVE || wParam == WA_ACTIVE) {
        // To switch to full screen mode, first hide all of the shell parts.
        // do not enable SHFS_HIDESTARTICON; it breaks the volume control on Diamond
		
		if (pSettings->doShowFullScreen) {
			dwState = SHFS_HIDETASKBAR | SHFS_HIDESIPBUTTON;

			// resize the main window to the size of the screen.
			SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXSCREEN), 
				GetSystemMetrics(SM_CYSCREEN));
		}
		else {
			dwState = SHFS_SHOWTASKBAR | SHFS_HIDESIPBUTTON;

			// resize the main window to the size of the work area.
			SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE);
		}

		SHFullScreen(hWnd, dwState);

		MoveWindow(hWnd, rc.left, rc.top, rc.right-rc.left, 
			rc.bottom-rc.top, TRUE);

        nHighlightedTab = nCurrentTab;
        bMouseDown = false;

        ShowWindow(hWnd, SW_SHOWNORMAL);
    }

    // The window is being deactivated and another program 
    // is being run... so minimize
    // lParam == NULL when the window being activated is not this app.
    else if (lParam == NULL) {		
		
		 if (pSettings->doExitOnMinimize && bSet==false) //ajige 3/31/10 still exits.
		{		 
            DestroyWindow(hWnd);
        }
        else if (bBackOnDeactivate) {
            PostMessage(hWnd, WM_COMMAND, CMD_BACK, 0);
            bBackOnDeactivate = false;
        }
    }

    // The window is being deactivated 
    // (maybe for "manage contact", or "edit contact")... 
    // restore it to non-fullscreen
	else {
		// To switch to normal mode, first show all of the shell parts.
		dwState = (SHFS_SHOWTASKBAR 
			| SHFS_SHOWSTARTICON 
			| SHFS_SHOWSIPBUTTON);

		SHFullScreen(hWnd, dwState);

		// Next resize the main window to the size of the work area.
		SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE);

		MoveWindow(hWnd, rc.left, rc.top, rc.right-rc.left,
			rc.bottom-rc.top, TRUE);
    }

    return DefWindowProc (hWnd, wMsg, wParam, lParam);
}

//-----------------------------------------------------------------------------
// DoTitlebarCallback - Process WM_TITLEBAR message for window
//
LRESULT DoTitlebarCallback (HWND hWnd, UINT wMsg, WPARAM wParam,
							LPARAM lParam) {

    RefreshTitlebar(lParam);
    InvalidateRect(hWnd, &rTitlebar, false);
    UpdateWindow(hWnd);
    return 0;
}

//-----------------------------------------------------------------------------
// DoSettingsTaintedCallback - Process WM_SETTINGS_TAINTED message for window
//
LRESULT DoSettingsTaintedCallback (HWND hWnd, UINT wMsg, WPARAM wParam,
								   LPARAM lParam) {

	if (lParam & SETTINGS_TAINTED_IDIALER) {
	   GetIDialerServiceName();
	   InvalidateRect(hWnd, &rTitlebar, false);
	}

	// if the skin or the language changed, we'll have to restart
	// restarting is not absolutely necessary, but it's easiest
	if (lParam & (SETTINGS_TAINTED_SKIN | SETTINGS_TAINTED_LANGUAGE)) {
	   DestroyWindow(hWnd);
	}

	UpdateWindow(hWnd);

	return 0;
}

//-----------------------------------------------------------------------------
// DoRecentsTaintedCallback - Process WM_RECENTS_TAINTED message for window
//
//LRESULT DoRecentsTaintedCallback (HWND hWnd, UINT wMsg, WPARAM wParam,
//                    LPARAM lParam) {
//
//    isRecentsTainted = true;
//
//    int screen = History[depth].screen;
//
//    if (hWnd == GetForegroundWindow() && (
//        screen == 1 || screen == 5)) {
//        PostMessage(hWnd, WM_COMMAND, CMD_RELOAD, NULL);
//    }
//
//    UpdateWindow(hWnd);
//
//    return 0;
//}

//-----------------------------------------------------------------------------
// DoPoomTaintedCallback - Process PIM_ITEM_*_* message for window
//
LRESULT DoPoomTaintedCallback (HWND hWnd, UINT wMsg, WPARAM wParam,
                    LPARAM lParam) {
	//MessageBox(0,L"taint",L"",0);
	//TCHAR newItem[MAX_PATH] = {0};
	//stToday.wDay=GroupArray[keyboardIndex].ID;
				//wsprintf(newItem, TEXT("%i,%i,%i"), stToday.wDay,stToday.wMonth,stToday.wYear);
				//MessageBox(0,L"wday,wmonth,wyear",newItem,0);
			// wParam = Item OID, lParam = Database OID.

	isPoomTainted = true;
	
			//ajige isFavoritesTainted = true;

    int screen = History[depth].screen;

    if (hWnd == GetForegroundWindow() && (
           screen == 0 || screen == 1|| screen == 2 || screen == 3 
        || screen == 4 || screen == 6
        )) {
        PostMessage(hWnd, WM_COMMAND, CMD_RELOAD, NULL);
    }

    UpdateWindow(hWnd);

    return 0;
}

//-----------------------------------------------------------------------------
// DoGestureCallback - Process WM_HTC_GESTURE message for window.
//
LRESULT DoGestureCallback (HWND hWnd, UINT wMsg, WPARAM wParam,
						   LPARAM lParam) {

	switch (wParam & ROTATION_MASK)	{
		case ROTATION_CLOCKWISE:
			PostMessage(hWnd, WM_KEYDOWN, VK_DOWN, NULL);
			break;
		case ROTATION_COUNTER:
			PostMessage(hWnd, WM_KEYDOWN, VK_UP, NULL);
			break;
	}
	return 0;
}

//-----------------------------------------------------------------------------
// DoTouchCallback - Process WM_HTC_TOUCH message for window.
//
LRESULT DoTouchCallback (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {
    HTCTOUCH_WPARAM touchW;
	memcpy(&touchW, &wParam, sizeof HTCTOUCH_WPARAM);

	// No need for this to check where or if the panel is being touched
    //HTCTOUCH_LPARAM touchL;	
	//memcpy(&touchL, &lParam, sizeof HTCTOUCH_LPARAM);
    
	if (touchW.Up == 0) {

		// If it's touched in the central region
		if(touchW.Where == 81 || touchW.Where == 17) {
			SENSORDATA sd;
			SensorGesturePoll(&sd);

			// Set the initial angle
			iInitialAngle = sd.AngleY;					

			// Start default timer speed
			SetTimer(hWnd, IDT_TIMER_SCROLL, REFRESH_RATE, (TIMERPROC)NULL);

			// We're G-Scrolling now!
			bGScrolling = true;							
		}
	}
	else {
		// We're no longer scrolling :(
		bGScrolling = false;							
	}

	return 0;
}


//-----------------------------------------------------------------------------
// DoSize - Process WM_SIZE message for window
//
LRESULT DoSize (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {
    
    switch (wParam) {
        case SIZE_RESTORED:
        case SIZE_MAXIMIZED:
        case SIZE_MAXSHOW:
	        InitSurface(hWnd);
            break;
        case SIZE_MINIMIZED:
			
            if (pSettings->doExitOnMinimize && bSet==false)
                DestroyWindow(hWnd);
    }

    return 0;
}

//-----------------------------------------------------------------------------
// DoMouseDown - Process WM_LBUTTONDOWN message for window
//

LRESULT DoMouseDown (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {

	LastX = ptMouseDown.x = LOWORD(lParam);
	LastY = ptMouseDown.y = HIWORD(lParam);
    tStartTime = ::GetTickCount();
    bMouseDown = true;

    // Touching the list stops the scrolling
    if (bScrolling
        && (
            PtInRect(&rList, ptMouseDown)
            || PtInRect(&rMenubar, ptMouseDown) 
            && !Screens[History[depth].screen].hasMenus
        )
    ) {
        KillTimer(hWnd, IDT_TIMER_SCROLL);
        KillTimer(hWnd, IDT_TIMER_SCROLL_TO);
        rClickRegion.top = -1;
        rClickRegion.bottom = -1;

        double v = Velocity;
        Velocity = 0;

        // Try to detect if they're just touching the list to stop it.
        // Maybe it's scrolling slowly enough that they want to click.
        if (v < -0.1 || v > 0.1)
            return 0;

        bScrolling = false;
    }

    if (bDisplayingPopup || bTransitioning) {
        return 0;
    }

    // invalidate the old click region too, in case it needs to be un-highlighted
    InvalidateRect(hWnd, &rClickRegion, FALSE);

    CalculateClickRegion(ptMouseDown);
    InvalidateRect(hWnd, &rClickRegion, FALSE);

    // virtual scroll bar
    if (LastX > rList.right * 8 / 10 
        && LastY >= rHeader.bottom 
        && LastY < rMenubar.top
        && depth == 1) {

        bScrolling = true;
        ScrollBar(LastY);
        InvalidateRect(hWnd, &rList, FALSE);
    }

    return 0;
}

//-----------------------------------------------------------------------------
// DoMouseMove - Process WM_MOUSEMOVE message for window
//
LRESULT DoMouseMove (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {

	int x = LOWORD(lParam);
	int y = HIWORD(lParam);
    int t = ::GetTickCount();

    if (bTransitioning||ptPopupType==ptKeyboard)//;bDisplayingPopup) 
	{  //prevents scrolling on the editpopup
    }
	
    else if (ptMouseDown.y >= rMenubar.top
        && Screens[History[depth].screen].hasMenus) 
	{
        if (y > rMenubar.top) {
            ptMouseDown.x = x;
            ptMouseDown.y = y;
            InvalidateRect(hWnd, &rMenubar, false);
        }
    }

    else if (ptMouseDown.y < rHeader.bottom) {
    }

		// "back" button in header bar
		/*ajige else if (ptMouseDown.y < rHeader.top + SCALE(HEADER_CLICK_HEIGHT) 
			&& ptMouseDown.x <= SCALE(HEADER_CLICK_HEIGHT)
			&& depth > 0
			) {
		}*/

    // "+" button in header bar, or * in detail view
	else if (ptMouseDown.y < rHeader.top + SCALE(HEADER_CLICK_HEIGHT) 
		&& ptMouseDown.x >= rList.right - SCALE(HEADER_CLICK_HEIGHT) 
        && (
            Screens[History[depth].screen].fnAdd != NULL
          //  || Screens[History[depth].screen].fnToggleFavorite != NULL  //5/3/10
        ) ) {

    }

	else if (bScrolling && Velocity == 20.0) {
        InvalidateRect(hWnd, &rClickRegion, false);
        rClickRegion.top = -1;
        rClickRegion.bottom = -1;
        rClickRegion.left = -1;
        rClickRegion.right = -1;
        ScrollBar(y);
        InvalidateRect(hWnd, &rList, false);
        UpdateWindow(hWnd);
	}

	else if (bDragging 
		|| abs(y - ptMouseDown.y) > SCALE(SCROLL_THRESHOLD)) 
	{
		//UnselectItem(); //5/3/10
		//ajige: only vertical drag 
        if (!bDragging) {
            UnselectItem();
            bDragging = true;
        }

        if (bScrolling) 
            bScrolling = false;

        // SCROLL
        History[depth].scrolled += LastY - y;
	    LastY = y;
	    LastX = x;

        Velocity = (double)(LastY - ptMouseDown.y) / (t - tStartTime);
        tEndTime = t;

        InvalidateRect(hWnd, 
            Screens[History[depth].screen].hasMenus ? &rList : &rContent, 
            FALSE);

        UpdateWindow(hWnd);
    }

    return 0;
}

//-----------------------------------------------------------------------------
// DoMouseUp - Process WM_LBUTTONUP message for window
//
LRESULT DoMouseUp (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {
    POINT pt = {0};
	int t = ::GetTickCount();
	TCHAR newItem[MAX_PATH] = {0};
	SYSTEMTIME stTemp=stToday;
	SYSTEMTIME stKeyboard=stToday; //to save orignal date 5/3/10
	
	
			// int nItem = pt.y / SCALE(DEFAULT_ITEM_HEIGHT);//GetPixelToItem(pt.y)+History[depth].scrolled/SCALE(DEFAULT_ITEM_HEIGHT)+1;
				//DataItem dItem = SelectItem(nItem);
    // This will trigger if the list was scrolling quickly, but
    // the user clicked to stop it.
	//if(!Screens[History[depth].screen].hasMenus)
		 //MessageBox(0,L"Details",L"",0);
	if (bScrolling
        && (
            PtInRect(&rList, ptMouseDown)
            || PtInRect(&rMenubar, ptMouseDown) 
            && !Screens[History[depth].screen].hasMenus
			)
		) 
	{
        bScrolling = false;
        InvalidateRect(hWnd, &rContent, FALSE);
        return 0;
    }
	
    if (bTransitioning)
        return 0;

    if (!bMouseDown)
        return 0;

	pt.x = LOWORD(lParam);
	pt.y = HIWORD(lParam);
    bMouseDown = false;
    InvalidateRect(hWnd, &rClickRegion, FALSE);

    // They clicked on the popup, no matter what screen
	if(bDisplayingPopup)//the keyboard
	{
		 //ajige 6/1 choose task based on letter
		if(CompareString(LOCALE_NEUTRAL, NORM_IGNORECASE, pSettings->sort_tasks, -1, TEXT("Alphabetical"), -1) == CSTR_EQUAL
			&& History[depth].screen==1)
		{
			StartTransition(hWnd, ttKeyboardShrink, SHRINK_KEYBOARD_PERIOD);//,NULL);
			int keyboardIndex = (pt.y / GroupHeight) 
				* (rScreen.right - rScreen.left) / GroupWidth 
				+ (pt.x - rScreen.left) / GroupWidth;
			
			ScrollTo(hWnd, GroupPosition[keyboardIndex]);
			UnselectItem();	
			nHighlightedTab=History[depth].screen;
			
		}
		/*else if (History[depth].screen==4 && ttEditExpand) //5/3/10
		{//not for calendar
				//==clicking on the popup
				//MessageBox(0,L"ttEditExpand",L"DoMouseUp",0);
			StartTransition(hWnd, ttEditShrink, SHRINK_KEYBOARD_PERIOD);//,NULL);
				//int keyboardIndex = (pt.y / GroupHeight) 
				//	* (rScreen.right - rScreen.left) / GroupWidth 
				//	+ (pt.x - rScreen.left) / GroupWidth;
			
			iLine=(pt.y-SCALE(DEFAULT_ITEM_HEIGHT)/2)/SCALE(DEFAULT_ITEM_HEIGHT);
				//TCHAR newItem[MAX_PATH] = {0};
				//wsprintf(newItem, TEXT("%i"), line);
				//MessageBox(0,L"expandit",newItem,0);
				//ScrollTo(hWnd, GroupPosition[keyboardIndex]);
				//UnselectItem();	
			UpdateItem(iLine,dItem);
				//nHighlightedTab=History[depth].screen;
		}*/
		else //dates
		{
			//TODO 5/3/10 tried to make it work so that when changing dates from the details screen
			//the stToday date won't be affected for the agenda screen, but it doesn't work
			if(pt.x-LastX>30) //next month
			{
				if (stTemp.wMonth==12)
				{
					stTemp.wMonth=1;
					stTemp.wYear++;
				}
				else
					stTemp.wMonth++;

					//if (!Screens[History[depth].screen].hasMenus) //5/3/10
					//	stKeyboard=stTemp;	
					//else
				stToday=stTemp;
				PostMessage(hWnd, WM_COMMAND, CMD_GOTO_CALENDAR, NULL);
			}
			else if(pt.x-LastX<-30)  //previous month
			{
				if (stTemp.wMonth==1)
				{
					stTemp.wMonth=12;
					stTemp.wYear--;
				}
				else
					stTemp.wMonth--;
					//if (!Screens[History[depth].screen].hasMenus) //5/3/10
					//	stKeyboard=stTemp;
					//else
				stToday=stTemp;	
				PostMessage(hWnd, WM_COMMAND, CMD_GOTO_CALENDAR, NULL);
			}

			else// if (bDisplayingPopup)  clicking a date
			{
				StartTransition(hWnd, ttKeyboardShrink, SHRINK_KEYBOARD_PERIOD);//,NULL);

				int keyboardIndex = (pt.y / GroupHeight) 
					* (rScreen.right - rScreen.left) / GroupWidth 
					+ (pt.x - rScreen.left) / GroupWidth;
			
						//5/13if(GroupArray[keyboardIndex].ID>0)
						//{//works for agenda and all apptms, not on tasks
						//	if (History[depth].screen<2)//.hgScreen<2) //tasks ajige should it scroll to the date??
						//		ScrollTo(hWnd, GroupPosition[keyboardIndex]);
						//	else
						//	{ //ajige 5/13 for all screens
			
				if(GroupArray[keyboardIndex].ID != 0)  //ajige 5/14 only update when a date is actually selected
				{										// allelimo: changed to != 0
						//UnselectItem();
							//ajige if (keyboardIndex < nKeyboardLetters) {	

						if(!Screens[History[depth].screen].hasMenus)//5/1/10 clicking calendar from details menu
							//wParam=itemoid
						{
							//if (dItem.isTask)
							{
								extern IPOutlookApp2 *             polApp;
								HRESULT    hr;
								ITask * pTask = NULL;
								IAppointment * pApp = NULL;								
								stKeyboard=stTemp;
								stKeyboard.wDay=GroupArray[keyboardIndex].ID;
						
								if (polApp == NULL) 
								{
									hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
														  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
									CHR(hr);			    
									hWnd = FindWindow (SZ_APP_NAME, NULL);
									hr = polApp->Logon((long)hWnd);
									CHR(hr);
								}
								hr = S_OK;

								if (FAILED(hr)) 
								{
										// If we failed to log on, don't keep the object around
									RELEASE_OBJ(polApp);
								}
								
								int oid = dItem.oId;
								if (oid == -1)
									return E_INVALIDARG;
								DATE dtToday;
								
								if (dItem.isTask)
								{
									SystemTimeToVariantTime(&stKeyboard, &dtToday);								
									hr = polApp->GetItemFromOid((CEOID)oid, (IDispatch**)&pTask);
									CHR(hr);
									if (0 == _tcscmp(dItem.szSecondaryText, pSettings->starts_string))
										hr=pTask->put_StartDate(dtToday);
									else if(0 == _tcscmp(dItem.szSecondaryText, pSettings->duedate_string))
										hr=pTask->put_DueDate(dtToday);
									CHR(hr);
									hr=pTask->Save();
									CHR(hr);
								}
								else
								{
									DATE dtDate;
									SYSTEMTIME stDate;
									hr = polApp->GetItemFromOid((CEOID)oid, (IDispatch**)&pApp);
									CHR(hr);
									if (0 == _tcscmp(dItem.szSecondaryText,pSettings->starts_string))
									{
										hr=pApp->get_Start(&dtDate);
										CHR(hr);
										VariantTimeToSystemTime(dtDate, &stDate);
										stKeyboard.wHour=stDate.wHour;
										stKeyboard.wMilliseconds=stDate.wMilliseconds;
										stKeyboard.wMinute=stDate.wMinute;
										stKeyboard.wSecond=stDate.wSecond;
										SystemTimeToVariantTime(&stKeyboard, &dtToday);	
										hr=pApp->put_Start(dtToday);
									}
									else if(0 == _tcscmp(dItem.szSecondaryText,pSettings->ends_string))
									{
										hr=pApp->get_End(&dtDate);
										CHR(hr);
										VariantTimeToSystemTime(dtDate, &stDate);
										stKeyboard.wHour=stDate.wHour;
										stKeyboard.wMilliseconds=stDate.wMilliseconds;
										stKeyboard.wMinute=stDate.wMinute;
										stKeyboard.wSecond=stDate.wSecond;
										SystemTimeToVariantTime(&stKeyboard, &dtToday);
										hr=pApp->put_End(dtToday);
									}
									CHR(hr);
									hr=pApp->Save();
									CHR(hr);
								}	
								isPoomTainted=true;							
							}	//if task  
							stToday.wMonth=stTemp.wMonth; //to keep original dates 5/3/10
						}
						else //all screeens except details
						{
							stToday.wDay=GroupArray[keyboardIndex].ID;
							DoPoomTaintedCallback(hWnd,wMsg,wParam,lParam);//ajige yes redraws list
						}
				}
				else  //agige 5/18 reset date when month is changed, but no date selected
					GetLocalTime(&stToday);
				UnselectItem();	
				nHighlightedTab=History[depth].screen;//.hgScreen; //ajige
			}
		}
	}
    // They clicked in the top in the agenda screen
	else if (LastY>=rHeader.top 
        && LastY < rHeader.top  + SCALE(HEADER_CLICK_HEIGHT)  //bottom//5/13 ajige from: top  +HEADER_CLICK_HEIGHT * vga
		&& History[depth].screen==2 
		&& pt.y >= rHeader.top //agige 5/19 added to be able to cancel when moving away
        && pt.y < rHeader.top + SCALE(HEADER_CLICK_HEIGHT))
	{
		int maxdays[] =
		{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
		};
		
		if((stToday.wYear%4 == 0 && stToday.wYear % 100 != 0) || stToday.wYear%400 == 0) //leapyear
			maxdays[1]=29;
		//next day 
		if(pt.x-LastX>30 ||  pt.x >= rList.right - SCALE(HEADER_CLICK_HEIGHT))
		{
			if(stToday.wDay==maxdays[stToday.wMonth-1])
			{
				stToday.wDay=1;
				if (stToday.wMonth==12)
				{
					stToday.wMonth=1;
					stToday.wYear++;
				}
				else				
					stToday.wMonth++;
			}
			else
				stToday.wDay++;
			//PostMessage(hWnd, WM_COMMAND, CMD_RELOAD, NULL);
		}
		//previous day
		else if(pt.x-LastX<-30 ||  pt.x <= SCALE(HEADER_CLICK_HEIGHT))
		{
			if(stToday.wDay==1)
			{
				if (stToday.wMonth==1)
				{
					stToday.wMonth=12;
					stToday.wYear--;
				}
				else
					stToday.wMonth--;
				stToday.wDay=maxdays[stToday.wMonth-1];
			}
			else
				stToday.wDay--;
			//PostMessage(hWnd, WM_COMMAND, CMD_RELOAD, NULL);
		}
		else //ajige 4/24: clicked in the middle
		{
			SYSTEMTIME stNow;
			GetLocalTime(&stNow);
			stToday.wDay=stNow.wDay;
			stToday.wMonth=stNow.wMonth;
			stToday.wYear=stNow.wYear;

		}
		PostMessage(hWnd, WM_COMMAND, CMD_RELOAD, NULL);
	}

// They clicked in the bottom menus
    else if (Screens[History[depth].screen].hasMenus 
        && PtInRect(&rMenubar, ptMouseDown) && PtInRect(&rMenubar, pt)) {
        int tab = pt.x * 5 / (rMenubar.right - rMenubar.left);

        nHighlightedTab = tab;

        if (tab == nCurrentTab && History[depth].screen == tab) {
            PostMessage(hWnd, WM_COMMAND, CMD_RELOAD, NULL);
        }
        else {
            PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, tab);
        }
    }

    // They scrolled the screen up too far
    else if (bDragging && History[depth].scrolled < minScrolled) {
        bDragging = false;
        ScrollTo(hWnd, minScrolled);
    }

    // They scrolled the screen down too far
    else if (bDragging && History[depth].scrolled > maxScrolled) {
        bDragging = false;
        ScrollTo(hWnd, maxScrolled);
    }

    // now we're scrolling
    else if (bDragging) {
		// First scroll right away!
		PostMessage(hWnd, WM_TIMER, IDT_TIMER_SCROLL, 0);

		// Then set the timer to scroll smoothly
        SetTimer(hWnd, IDT_TIMER_SCROLL, 
            REFRESH_RATE, (TIMERPROC) NULL);
        bScrolling = true;
        bDragging = false;
    } 

    // Click in header bar details
				
				//else if (LastY>=rHeader.top 
				//    && LastY < rHeader.top  +HEADER_CLICK_HEIGHT * vga  //bottom//5/13 ajige from: top  +HEADER_CLICK_HEIGHT * vga
				///	&& Screens[History[depth].screen].parent == 0 
				//	&& pt.y >= rHeader.top //agige 5/19 added to be able to cancel when moving away
				//    && pt.y < rHeader.top + HEADER_CLICK_HEIGHT * vga )
				//{
    else if (depth > 0 && pt.y >= rHeader.top 
        && pt.y < rHeader.top + SCALE(HEADER_CLICK_HEIGHT) 
        && pt.x <= SCALE(HEADER_CLICK_HEIGHT)
		&& Screens[History[depth].screen].parent == 0 ) { //ajige 4/23
				//&& Screens[History[depth].screen].parent >= 0 ) {
				//"back" button in header bar, only for details screen, agenda see above
			PostMessage(hWnd, WM_COMMAND, CMD_BACK, EXPAND_DETAILS_PERIOD); 				
    }
	
    // "+" button in header bar
    else if (pt.y >= rHeader.top 
        && pt.y < rHeader.top + SCALE(HEADER_CLICK_HEIGHT) 
        && pt.x >= rList.right - SCALE(HEADER_CLICK_HEIGHT) 
        && Screens[History[depth].screen].fnAdd != NULL) {

        PostMessage(hWnd, WM_COMMAND, CMD_ADD, NULL);
    }

    // They clicked in the titlebar
    // no matter what the screen type is
	else if (PtInRect(&rTitlebar, ptMouseDown) && PtInRect(&rTitlebar, pt)) {
        ShowWindow(hWnd, SW_MINIMIZE);
	}

    // Clicked a list item
    else if (pt.y >= rList.top && GetItemCount() > 0 && pt.x>SCALE(MENU_BAR_ICON_WIDTH)/2) 
	{
			//int index = -1;//0;//-1;
        pt.y += History[depth].scrolled - rList.top;
        int nItem = GetPixelToItem(pt.y);
		if (!CanSelectItem(nItem))
			return 0;
		if (Screens[History[depth].screen].hasMenus) //5/5/10
			PostMessage(hWnd, WM_COMMAND, CMD_CLICK_ITEM, nItem);
		else
			PostMessage(hWnd, WM_COMMAND, CMD_EDIT_ITEM, nItem);//5/5/10
	}

	//Detail List	
	 if(!Screens[History[depth].screen].hasMenus)
			//else if(Screens[History[depth].screen].hgScreen==4)//data.type]==diLocation)
	{		//clicking on the edit screen
				//pt.y += History[depth].scrolled - rList.top;
				//pt.y -= History[depth].scrolled;// + rList.top;
				//int y = pt.y + History[depth].scrolled;// + rContent.top;	
				
				//pt.y+=History[depth].scrolled
		
			int nItem = pt.y / SCALE(DEFAULT_ITEM_HEIGHT);//GetPixelToItem(pt.y)+History[depth].scrolled/SCALE(DEFAULT_ITEM_HEIGHT)+1;
			//DataItem  5/2/10
			dItem = SelectItem(nItem);
			
		switch(dItem.type)
		{
			case diDateTime:
				//UnselectItem();
				ptPopupType=ptKeyboard;
				StartTransition(hWnd, ttKeyboardExpand, EXPAND_KEYBOARD_PERIOD);
				break;
			
		//	case diImportance:
		//	case diSensitivity:
				//UnselectItem();
		//		ptPopupType=ptEdit;
		//		StartTransition(hWnd, ttEditExpand, EXPAND_KEYBOARD_PERIOD);
		//		break;

			case diStatus:
				if (dItem.isTask)
				{
					dItem.isComplete = !dItem.isComplete;//true;
					UpdateItem(dItem.isComplete,dItem);
					/*extern IPOutlookApp2 *             polApp;
					HRESULT    hr;
					ITask * pTask = NULL;
					if (polApp == NULL) 
					{
						hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
											  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
						CHR(hr);			    
						hWnd = FindWindow (SZ_APP_NAME, NULL);
						hr = polApp->Logon((long)hWnd);
						CHR(hr);
					}
					hr = S_OK;

					if (FAILED(hr)) 
					{
							// If we failed to log on, don't keep the object around
						RELEASE_OBJ(polApp);
					}
					int oid = dItem.oId;
					if (oid == -1)
						return E_INVALIDARG;
				
					hr = polApp->GetItemFromOid((CEOID)dItem.oId, (IDispatch**)&pTask);
					CHR(hr);
					pTask->get_Complete(&dItem.isComplete);							
					if (dItem.isComplete)
					{					
						hr=pTask->put_Complete(VARIANT_FALSE); 
						CHR(hr);
					}
					else
					{
						hr=pTask->put_Complete(VARIANT_TRUE);  //or -1
						CHR(hr);
					}
					hr=pTask->Save();
					CHR(hr);
					dItem.isComplete = !dItem.isComplete;//true;
					isPoomTainted=true;	*/						
				}	//if task   
				else
				{
					ptPopupType=ptEdit;
					StartTransition(hWnd, ttEditExpand, EXPAND_KEYBOARD_PERIOD);
				}
				break;
			case diOccurs:
			case diReminder:
				if (dItem.isTask)
				{	
					UpdateItem(dItem.isComplete,dItem);
					/*extern IPOutlookApp2 *             polApp;
					HRESULT    hr;
					ITask * pTask = NULL;
					if (polApp == NULL) 
					{
						hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
											  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
						CHR(hr);			    
						hWnd = FindWindow (SZ_APP_NAME, NULL);
						hr = polApp->Logon((long)hWnd);
						CHR(hr);
					}
					hr = S_OK;

					if (FAILED(hr)) 
					{
							// If we failed to log on, don't keep the object around
						RELEASE_OBJ(polApp);
					}
					int oid = dItem.oId;
					if (oid == -1)
						return E_INVALIDARG;
					VARIANT_BOOL bRemind;
					hr = polApp->GetItemFromOid((CEOID)dItem.oId, (IDispatch**)&pTask);
					CHR(hr);
					pTask->get_ReminderSet(&bRemind);	
					//doesn't work correctly. To turn reminder off, set complete to true
					if (bRemind)
					{	
						//works
						hr=pTask->put_ReminderSet(VARIANT_FALSE); 
						CHR(hr);
					}
					else
					{
						//doesn't work:
						hr=pTask->put_ReminderSet(VARIANT_TRUE);  //or -1
						CHR(hr);
						//TODO also need to set reminder options?? 
						//as it doesn't seem to work
					}
					hr=pTask->Save();
					CHR(hr);
					isPoomTainted=true;			*/				
				}	//if task if (dItem.isTask)				
				break;

			/*case diOccurs:
				if (dItem.isTask)
			{
				extern IPOutlookApp2 *             polApp;
				HRESULT    hr;
				ITask * pTask = NULL;
				if (polApp == NULL) 
				{
					hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
										  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
					CHR(hr);			    
					hWnd = FindWindow (SZ_APP_NAME, NULL);
					hr = polApp->Logon((long)hWnd);
					CHR(hr);
				}
				hr = S_OK;

				if (FAILED(hr)) 
				{
						// If we failed to log on, don't keep the object around
					RELEASE_OBJ(polApp);
				}
				int oid = dItem.oId;
				if (oid == -1)
					return E_INVALIDARG;
				
				hr = polApp->GetItemFromOid((CEOID)dItem.oId, (IDispatch**)&pTask);
				CHR(hr);
				VARIANT_BOOL bRecur;
				pTask->get_IsRecurring(&bRecur);							
				if (bRecur)
				{					
					hr=pTask->ClearRecurrencePattern();//(VARIANT_FALSE); 
					//pTask->
					CHR(hr);
				}
				else
				{
					//TODO there is no put_recurrence????
					//hr=pTask->put_Complete(VARIANT_TRUE);  //or -1
					//CHR(hr);
				}
				hr=pTask->Save();
				CHR(hr);
				dItem.isComplete = !dItem.isComplete;//true;
				isPoomTainted=true;							
			}	//if task 
				break;*/

			case diEditButton:
				extern IPOutlookApp2 *             polApp;
				HRESULT    hr;
				//ITask * pTask = NULL;
				IItem * pItem = NULL;
				IDispatch * pDisp = NULL;

				if (polApp == NULL) 
				{
					hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
										  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
					CHR(hr);
			    
					hWnd = FindWindow (SZ_APP_NAME, NULL);
					hr = polApp->Logon((long)hWnd);
					CHR(hr);
				}

				hr = S_OK;				
				int oid = dItem.oId;
				if (oid == -1)
					return E_INVALIDARG;
				hr = polApp->GetItemFromOid(oid, &pDisp);
				CHR(hr);
				hr = pDisp->QueryInterface(IID_IItem, (LPVOID*)&pItem);
				CHR(hr);
				//hWnd = FindWindow (SZ_APP_NAME, NULL);
        		hr = pItem->Display(hWnd);
				CHR(hr);
				break;

		}
		/*if(dItem.type==diDateTime && !bExpanded && !bScrolling) //4/30/10
		{
				//TCHAR newItem[MAX_PATH] = {0};
			UnselectItem();
			StartTransition(hWnd, ttKeyboardExpand, EXPAND_KEYBOARD_PERIOD);//,dItem); 
			
		}
		else if(dItem.type==diImportance
			|| dItem.type==diSensitivity)//5/3/10
		{
			UnselectItem();
			ptPopupType=ptEdit;
			StartTransition(hWnd, ttEditExpand, EXPAND_KEYBOARD_PERIOD);
		}

		else if(dItem.type==diStatus && !bExpanded) //4/30/10
		{
			if (dItem.isTask)
			{
				extern IPOutlookApp2 *             polApp;
				HRESULT    hr;
				ITask * pTask = NULL;
				if (polApp == NULL) 
				{
					hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
										  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
					CHR(hr);			    
					hWnd = FindWindow (SZ_APP_NAME, NULL);
					hr = polApp->Logon((long)hWnd);
					CHR(hr);
				}
				hr = S_OK;

				if (FAILED(hr)) 
				{
						// If we failed to log on, don't keep the object around
					RELEASE_OBJ(polApp);
				}
				int oid = dItem.oId;
				if (oid == -1)
					return E_INVALIDARG;
				
				hr = polApp->GetItemFromOid((CEOID)dItem.oId, (IDispatch**)&pTask);
				CHR(hr);
				pTask->get_Complete(&dItem.isComplete);							
				if (dItem.isComplete)
				{					
					hr=pTask->put_Complete(VARIANT_FALSE); 
					CHR(hr);
				}
				else
				{
					hr=pTask->put_Complete(VARIANT_TRUE);  //or -1
					CHR(hr);
				}
				hr=pTask->Save();
				CHR(hr);
				dItem.isComplete = !dItem.isComplete;//true;
				isPoomTainted=true;							
			}	//if task           
		}

		else if(dItem.type==diReminder && !bExpanded) //4/30/10
		{
			if (dItem.isTask)
			{			
				extern IPOutlookApp2 *             polApp;
				HRESULT    hr;
				ITask * pTask = NULL;
				if (polApp == NULL) 
				{
					hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
										  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
					CHR(hr);			    
					hWnd = FindWindow (SZ_APP_NAME, NULL);
					hr = polApp->Logon((long)hWnd);
					CHR(hr);
				}
				hr = S_OK;

				if (FAILED(hr)) 
				{
						// If we failed to log on, don't keep the object around
					RELEASE_OBJ(polApp);
				}
				int oid = dItem.oId;
				if (oid == -1)
					return E_INVALIDARG;
				VARIANT_BOOL bRemind;
				hr = polApp->GetItemFromOid((CEOID)dItem.oId, (IDispatch**)&pTask);
				CHR(hr);
				pTask->get_ReminderSet(&bRemind);	
				//doesn't work correctly. To turn reminder off, set complete to true
				if (bRemind)
				{	
					//works
					hr=pTask->put_ReminderSet(VARIANT_FALSE); 
					CHR(hr);
				}
				else
				{
					//doesn't work:
					hr=pTask->put_ReminderSet(VARIANT_TRUE);  //or -1
					CHR(hr);
					//TODO also need to set reminder options?? 
					//as it doesn't seem to work
				}
				hr=pTask->Save();
				CHR(hr);
				//dItem.isComplete = !dItem.isComplete;//true;
				isPoomTainted=true;							
			}	//if task               
		}	

		else if(dItem.type==diOccurs && !bExpanded) //4/30/10
		{
			if (dItem.isTask)
			{
				extern IPOutlookApp2 *             polApp;
				HRESULT    hr;
				ITask * pTask = NULL;
				if (polApp == NULL) 
				{
					hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
										  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
					CHR(hr);			    
					hWnd = FindWindow (SZ_APP_NAME, NULL);
					hr = polApp->Logon((long)hWnd);
					CHR(hr);
				}
				hr = S_OK;

				if (FAILED(hr)) 
				{
						// If we failed to log on, don't keep the object around
					RELEASE_OBJ(polApp);
				}
				int oid = dItem.oId;
				if (oid == -1)
					return E_INVALIDARG;
				
				hr = polApp->GetItemFromOid((CEOID)dItem.oId, (IDispatch**)&pTask);
				CHR(hr);
				VARIANT_BOOL bRecur;
				pTask->get_IsRecurring(&bRecur);							
				if (bRecur)
				{					
					hr=pTask->ClearRecurrencePattern();//(VARIANT_FALSE); 
					//pTask->
					CHR(hr);
				}
				else
				{
					//TODO there is no put_recurrence????
					//hr=pTask->put_Complete(VARIANT_TRUE);  //or -1
					//CHR(hr);
				}
				hr=pTask->Save();
				CHR(hr);
				dItem.isComplete = !dItem.isComplete;//true;
				isPoomTainted=true;							
			}	//if task           
		}

		else if(dItem.type==diEditButton && !bExpanded) //4/22/10
			{
				extern IPOutlookApp2 *             polApp;
				HRESULT    hr;
				//ITask * pTask = NULL;
				IItem * pItem = NULL;
				IDispatch * pDisp = NULL;

				if (polApp == NULL) 
				{
					hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
										  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
					CHR(hr);
			    
					hWnd = FindWindow (SZ_APP_NAME, NULL);
					hr = polApp->Logon((long)hWnd);
					CHR(hr);
				}

				hr = S_OK;				
				int oid = dItem.oId;
				if (oid == -1)
					return E_INVALIDARG;
				hr = polApp->GetItemFromOid(oid, &pDisp);
				CHR(hr);
				hr = pDisp->QueryInterface(IID_IItem, (LPVOID*)&pItem);
				CHR(hr);
				//hWnd = FindWindow (SZ_APP_NAME, NULL);
        		hr = pItem->Display(hWnd);
				CHR(hr);
				//hr = polApp->GetItemFromOid((CEOID)dItem.oId, (IDispatch**)&pTask);
				//CHR(hr);
				//hr=pTask->Display();
				//CHR(hr);
			}
			else //not editbutton
			{
			//if(bExpanded)
			//	UnselectItem();			
					//int y = pt.y + Scrolled - rContent.top;//
					//ExpandIt(hWnd, nItem);//index);
			int y = pt.y;// + History[depth].scrolled - rContent.top;
				//ExpandIt(hWnd, nItem);//index);
				//int y =History[depth].scrolled - rList.top;
			int index = -1;
			
				//taskdetails(subject, priority, status, start, due, occurs, reminder, categories, sensitivity, notes)
				//taskExpand(stEdit,stList, stList, stCalendar, stCalendar, stOnOff, stOnOff, stList,stList, stEdit)
				
			// They clicked above the expanded part
			if (y / SCALE(DEFAULT_ITEM_HEIGHT) <= nExpandedIndex
				&&bExpanded==false)
					//if (y  <= nExpandedIndex) 
			{
				index = y / SCALE(DEFAULT_ITEM_HEIGHT);
				
				if(nExpandedIndex>-1)//when nothing is chosen
					StartTransition(hWnd,ttContract,150);//,NULL);
				nQueuedExpandedIndex =index;
				ExpandIt(hWnd, nItem);	
				iLine=nItem;
			}

				// They clicked below the expanded part
			else if ((y - rExpandedHeight) / SCALE(DEFAULT_ITEM_HEIGHT) > nExpandedIndex
				&&bExpanded==false)
			{
				index = (y - rExpandedHeight) / SCALE(DEFAULT_ITEM_HEIGHT);
				//int y = pt.y + History[depth].scrolled - rContent.top;
				if(nExpandedIndex>-1)//when nothing is chosen
					StartTransition(hWnd,ttContract,150);//,NULL);
				
				nQueuedExpandedIndex =index;
				ExpandIt(hWnd, nItem);		
				iLine=nItem;	
					//int rPartialHeight = trTransitionType == ttExpand
					//	? (int)(dTransitionPct * rExpandedHeight)
					//		: (int)((1.0 - dTransitionPct) * rExpandedHeight);
					//	rContent.top = rContent.bottom;
					//	rContent.bottom += rPartialHeight;
					//	rContent.left = SCALE(LIST_ITEM_INDENT);
					//	rContent.right -= rContent.left;
					//	RECT rItemClip;
					//	IntersectRect(&rItemClip, &rContent, &rClip);
					//	DrawListDetailsOn(hdc, rContent, rItemClip, value);
			}

				// They clicked on the expanded part
			else if (bExpanded && index ==-1 )//
				//if(index == -1) 
			{		//int y = pt.y + History[depth].scrolled;// - rContent.top;
					//TCHAR newItem[MAX_PATH] = {0};
					//wsprintf(newItem, TEXT("%i,%i,%i"), nExpandedIndex,nItem,iLine);
					//MessageBox(0,L"nExpandedIndex,nItem,iLine",newItem,0);

				switch (TaskEdits[nExpandedIndex].type) 
				{	
					//TODO difficult to choose when expanded list extends below screen.
					case stList:
						index = (y - (SCALE(DEFAULT_ITEM_HEIGHT) * nExpandedIndex)) 
							/ SCALE(DEFAULT_ITEM_HEIGHT) -1;//- 1;
								// They clicked something starting with "AUTO",
								// so the proper setting value for this is ""
								//else 
								//if (EditOptions[index] 
								//    == _tcsstr(EditOptions[index], SZ_AUTO)) {
								   // EditValuesT[nExpandedIndex][0] = '\0';
							   // }

							   // else 
						{
							  //  StringCchCopy(EditValuesT[nExpandedIndex], 
							  //      MAX_LOADSTRING, EditOptions[index]);
							//	StringCchCopy(dItem.szPrimaryText, 
							 //       MAX_LOADSTRING, EditOptions[index]);

							//to update task for priority 4/21/10 works
						extern IPOutlookApp2 *             polApp;
						 HRESULT    hr;
						 ITask * pTask = NULL;
						if (polApp == NULL) 
						{
							hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
											  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
							CHR(hr);
				    
							hWnd = FindWindow (SZ_APP_NAME, NULL);
							hr = polApp->Logon((long)hWnd);
							CHR(hr);
						}

						hr = S_OK;

						Error:
							//RELEASE_OBJ(pItem);//ajige moved 
							//RELEASE_OBJ(pFolder);//ajige moved 
						if (FAILED(hr)) {
							// If we failed to log on, don't keep the object around
							RELEASE_OBJ(polApp);
						}
						int oid = dItem.oId;
						if (oid == -1)
						return E_INVALIDARG;
					
						hr = polApp->GetItemFromOid((CEOID)dItem.oId, (IDispatch**)&pTask);
						CHR(hr);
							
						if (iLine==1)
							hr=pTask->put_Importance(index);//put_Complete(VARIANT_FALSE); 
						else if (iLine==8)
							hr=pTask->put_Sensitivity(index);
						hr=pTask->Save();
						CHR(hr);
						isPoomTainted=true;
							//end 4/21/10
						InvalidateRect(hWnd, &rContent, false);
                    }
					
					bExpanded=false;
                    StartTransition(hWnd, ttContract);//, 150,NULL);
					index=0;
                    break;
                case stOnOff:					
                    // we should never get here
                    break;
            }// endswitch (TaskEdits[nExpandedIndex].type) {
        }//end if(index == -1)
						//if this code=> can only choose once.
						//else if(index < ARRAYSIZE(TaskEdits))
						//{
						//	if(nExpandedIndex >-1)
						//	{
						//		StartTransition(hWnd,ttContract,150);
						//	}
						//	switch (TaskEdits[index].type)
						//	{
						//	case stList:
						//		if(index !=nExpandedIndex && nExpandedIndex >-1)
						//			nQueuedExpandedIndex =index;
						//		if(!bTransitioning)
						//			ExpandIt(hWnd,index);
						//		break;
						//	case stOnOff:
						//		EditValuesT[index][0] 
						//		= EditValuesT[index][0]=='0'?'1':'0';
						//		break;
						//	}
						//}
						//InvalidateRect(hWnd,&rContent,FALSE);
		}*/
		Error:
		;
			// Free resources.
			//HeapFree(hHeap, 0, pVals);
			//RELEASE_OBJ(pFolderIItem);
			//RELEASE_OBJ(pFolder);
	} //end screen 4     		
			
	//}
	//clicked complete box //ajige 1/21/10 /4/10/10
	else if(pSettings->doEnableCheck && pt.y >= rList.top && GetItemCount() > 0 && pt.x<SCALE(MENU_BAR_ICON_WIDTH)/2)
	{	
		pt.y += History[depth].scrolled - rList.top;
		int nItem = GetPixelToItem(pt.y);	
		PostMessage(hWnd, WM_COMMAND, CMD_COMPLETE, nItem);	
	}

    UpdateWindow(hWnd);

    return 0;
}

//-----------------------------------------------------------------------------
// DoTimer - Process WM_TIMER message for window
//
LRESULT DoTimer (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {

    DWORD t = ::GetTickCount();
    DWORD dt = 0;
    double s = 0.0;
    RECT * pr;

	switch (wParam)	{

        ///// TIMER for scrolling
	    case IDT_TIMER_SCROLL:

            // Time
            dt = t - tEndTime;

            // Velocity
            if (History[depth].scrolled < minScrolled)
                Velocity = (double)(History[depth].scrolled - minScrolled) / 2 / dt;
            else if (History[depth].scrolled > maxScrolled)
                Velocity = (double)(History[depth].scrolled - maxScrolled) / 2 / dt;
            else {
                double dv = Velocity * FRICTION_COEFF * dt;
                if (fabs(dv) > fabs(Velocity)) 
                    Velocity = 0;
                else 
			        Velocity = Velocity - dv;

				// Gravity
				if (bGScrolling) {
					SENSORDATA sd;
					SensorGesturePoll(&sd);
					int sign = sd.AngleY < iInitialAngle ? -1 : 1;
					int dangle = abs(sd.AngleY - iInitialAngle);
					double radians = dangle * 3.141592654 / 180.0;
					Velocity += sin(radians) * pSettings->gravity * sign;
				}
            }

            // Displacement
            s = Velocity * dt;
            if (s < 0 && s > -1 && History[depth].scrolled < minScrolled)
                s = -1;
            else if (s > 0 && s < 1 && History[depth].scrolled > maxScrolled)
                s = 1;
            
            // We're done scrolling
            if ((int)s == 0 && !bGScrolling) {
                KillTimer(hWnd, IDT_TIMER_SCROLL);
		        bScrolling = false;
		        Velocity = 0;
            }

            History[depth].scrolled -= (int)s;
            tEndTime = t;
            pr = Screens[History[depth].screen].hasMenus ? &rList : &rContent;
            InvalidateRect(hWnd, pr, false);
		    break;

        ///// TIMER for scroll to
        case IDT_TIMER_SCROLL_TO:
            KillTimer(hWnd, IDT_TIMER_SCROLL);
            Scroll_TimeCounter = (double)(t - Scroll_StartTime);
            if (Scroll_TimeCounter < Scroll_Duration) {
                bScrolling = true;

                // Cubic
                double amount = Scroll_Change
                    * (pow(Scroll_TimeCounter/Scroll_Duration - 1, 3) + 1);
                Velocity = (amount - Scroll_StartPosition) / Scroll_TimeCounter;
                History[depth].scrolled = Scroll_StartPosition + (int)amount;
            }
            else {
                bScrolling = false;
                Velocity = 0;
                KillTimer(hWnd, IDT_TIMER_SCROLL_TO);
                History[depth].scrolled = Scroll_Change + Scroll_StartPosition;
            }
            InvalidateRect(hWnd, Screens[History[depth].screen].hasMenus 
                ? &rList : &rContent, false);
            break;

        case IDT_TIMER_TRANSITION:
            dTransitionPct = min(1.0, (double)(t - dwTransitionStart) 
                / nTransitionDuration);
		//for edit 4/19/10
/*	if (Screens[History[depth].screen].parent ==4 
				&& dTransitionPct >= 1.0) {
                dTransitionPct = 1.0;
                bTransitioning = false;

                KillTimer(hWnd, IDT_TIMER_TRANSITION);

                if (nQueuedExpandedIndex > -1) {
                    int tmp = nQueuedExpandedIndex;
                    nQueuedExpandedIndex = -1;
                    ExpandIt(hWnd, tmp);
                }
                else if (trTransitionType == ttContract) {
                    nExpandedIndex = -1;
                    rExpandedHeight = 0;
                }
                CalculateHeights();
            }*/
			//4/19 end
            InvalidateRect(hWnd, &rScreen, false);
            break;
	} 

	UpdateWindow(hWnd);
    return 0;
}

//-----------------------------------------------------------------------------
// DoKeyDown - Process WM_KEYDOWN message for window
//
LRESULT DoKeyDown (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {

    int top = 0;
    int bot = 0;
    bool bRepeating = (lParam & (1 << 30)) != 0;
    int index;

    if (bTransitioning || bDisplayingPopup) //ajige, in order to be able to switch months
        return 0;

    if (bScrolling) {
        KillTimer(hWnd, IDT_TIMER_SCROLL);
	    bScrolling = false;
	    Velocity = 0;
    }

    if (bRepeating) {
        nKeyRepeatCount++;
        if (nKeyRepeatCount < 10)
            bRepeating = false;
        else if (nKeyRepeatCount % 5 != 0)
            return 0;
    }
    else {
        nKeyRepeatCount = 0;
    }

	switch (wParam) {
		case VK_UP:
			index 
				= !bRepeating && GetCurrentItemIndex() == 0
				? SelectLastItem()
				: SelectPreviousItem(
				GetPixelToItem(History[depth].scrolled + rListHeight),
				bRepeating);

            if (index == -1)
                break;

			// make sure the selected item is visible
			top = GetStartPosition(index);
			bot = top + GetItemHeight(index);

            if (bScrolling) {
                History[depth].scrolled = max(0, 
                    min(top, ListHeight - rListHeight));
            }
			else if (
                   top < History[depth].scrolled 
                || bot > History[depth].scrolled + rListHeight
            ) {
                History[depth].scrolled = max(0, bot - rListHeight);
            }

			break;

	    case VK_DOWN:
			index 
				= !bRepeating && GetCurrentItemIndex() == GetItemCount() - 1
				? SelectFirstItem()
				: SelectNextItem(
				GetPixelToItem(History[depth].scrolled),
				bRepeating);

            if (index == -1)
                break;

			// make sure the selected item is visible
			top = GetStartPosition(index);
			bot = top + GetItemHeight(index);

            if (bScrolling) {
                History[depth].scrolled = max(0, 
                    min(top, ListHeight - rListHeight));
            }
            else if (
                   top < History[depth].scrolled 
                || bot > History[depth].scrolled + rListHeight
            ) {
                History[depth].scrolled = min(top, ListHeight - rListHeight);
            }

			break;

// todo: check this
//ajige: add code for agenda screen, calendar should be ok
        case VK_LEFT:
			if(bDisplayingPopup)
			{
				if (stToday.wMonth==1)
				{
					stToday.wMonth=12;
					stToday.wYear--;
				}
				else
					stToday.wMonth--;	
				PostMessage(hWnd, WM_COMMAND, CMD_GOTO_CALENDAR, NULL);
			}
            else if (nCurrentTab > 0 && Screens[History[depth].screen].hasMenus)
                PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, nCurrentTab - 1);
            else if (depth > 0)
                PostMessage(hWnd, WM_COMMAND, CMD_BACK, EXPAND_DETAILS_PERIOD);
            break;

        case VK_RIGHT:
			if(bDisplayingPopup)
			{
				if (stToday.wMonth==12)
				{
					stToday.wMonth=1;
					stToday.wYear++;
				}
				else
					stToday.wMonth++;
				PostMessage(hWnd, WM_COMMAND, CMD_GOTO_CALENDAR, NULL);
			}
            else if (nCurrentTab < 2)
                PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, nCurrentTab + 1);
            else if (nCurrentTab == 2)
                PostMessage(hWnd, WM_COMMAND, CMD_GOTO_SETTINGS, NULL);
			
            break;

	    case VK_TACTION:
			index = GetCurrentItemIndex();
			if (index >= 0) {
				ptMouseDown.x = rList.right / 2;
				if (Screens[History[depth].screen].hasMenus) //5/5/10
					PostMessage(hWnd, WM_COMMAND, CMD_CLICK_ITEM, index);
				else
					PostMessage(hWnd, WM_COMMAND, CMD_EDIT_ITEM, index);//5/5/10
			}
			break;

        //ajige3/31/10 
		/*case VK_TTALK:
            PostMessage(hWnd, WM_COMMAND, CMD_GREEN_BUTTON, NULL);
            return 0;
            break;*/

		default:
			// Jump to this key in the alphabet
			PostMessage(hWnd, WM_COMMAND, CMD_JUMP_TO, (LPARAM)wParam);
			break;
	}

    InvalidateRect(hWnd,
        Screens[History[depth].screen].hasMenus ? &rList : &rContent,
        FALSE);
	UpdateWindow(hWnd);

    return 0;
}

//-----------------------------------------------------------------------------
// ReloadThread - Function to run as a thread, to reload the current list
//
void ReloadThread(LPVOID lpvThreadParam) {
    DataItem * parent = depth > 0 ? &History[depth-1].data : NULL;
    ListLoad(parent, Screens[History[depth].screen], pSettings);
	CalculateHeights();
    HWND hWnd = (HWND)lpvThreadParam;
    PostMessage(hWnd, WM_COMMAND, CMD_REFRESH, 0);
    return;
}

//-----------------------------------------------------------------------------
// DoCommand - Process WM_COMMAND message for window
//
LRESULT DoCommand (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {
    DataItem * parent = NULL;
    //DataItem dItem; //5/5/10
	DataItem diEdit; //5/5/10
    int newScreen = 0;
    //POINT pt;
    float x = 0;
    float y = 0;
	HRESULT hr = E_FAIL;
	TCHAR * pLetter = 0;
	//HRESULT hr = S_OK;
					//IDispatch * pDisp = NULL;
				IItem * pItem = NULL;
				ITask * pTask = NULL;
					//2/12	BSTR buffer = NULL;
	//			HWND hWnd = 0;
				extern IPOutlookApp2 *             polApp;

    switch (wParam) {
        case CMD_GOTO_APPS:
            PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, 0);
            break;

        case CMD_GOTO_TASKS:
            PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, 1);
            break;

        case CMD_GOTO_AGENDA:
            PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, 2);
            break;

        case CMD_GOTO_SETTINGS:	//allelimo: (note) in iAgenda the dialer tab is actually the Contact tab
			RunSettings();		//ajige3/31/10 go to settins instead

				//if (pSettings->doExitOnAction)
				//    DestroyWindow(hWnd);
            break;

        case CMD_GOTO_CALENDAR:
					//ajige Commented out the below code, so the screen stays on agenda when going to the keyboard
				   // if (nCurrentTab == 2 && depth == 1))
					 //   nHighlightedTab = 2;
					//else
					  //  SendMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, 2);

				//allelimo: keep the highlight on the "starting" tab
			nHighlightedTab = nCurrentTab;

            StartTransition(hWnd, ttKeyboardExpand, EXPAND_KEYBOARD_PERIOD);//,NULL);
            break;

		// allelimo: I'm not sure about the next function, probably it is not needed?
		// it comes from 0.94

		// This will do a quick "jump" to details for a particular
		// contact. It will override the history as well. \//5/4/10 newver called TODO
		case CMD_GOTO_DETAILS:
			if (!lParam) {
				SendMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, 2);
				break;
			}

			// Manually build the history, so the "back" button works right
			// Categories
			History[0].screen = Screens[2].parent;
			History[0].scrolled = 0;
			History[0].selectedIndex = -1;
			History[0].data.ID = 0;
			StringCchCopy(History[0].data.szPrimaryText, 
				PRIMARY_TEXT_LENGTH, 
				pSettings->agenda_string);

			// "Agenda"
			History[1].screen = 2;
			History[1].scrolled = 0;
			History[1].selectedIndex = -1;
			History[1].data.ID = lParam;
			History[1].data.oId = lParam;

			// "Details"
			History[2].screen = 4;
			History[2].scrolled = -rListHeight;
			History[2].selectedIndex = -1;

			depth = 2;
			parent = &History[1].data;
			PostMessage(hWnd, WM_COMMAND, CMD_RELOAD, NULL);
			break;

        case CMD_SWITCH_TAB:
		
            // there are only 5 tabs...
            if (lParam < 0 || lParam > 4)
                break;
		
            if (3 == lParam) {
                PostMessage(hWnd, WM_COMMAND, CMD_GOTO_SETTINGS, NULL);//5/15/10 TODO should be settings
                break;
            }

            if (4 == lParam) {
                PostMessage(hWnd, WM_COMMAND, CMD_GOTO_CALENDAR, NULL);
                break;
            }

            // if we get here, 0 <= lParam <= 2. perfect.

            SetCursor(LoadCursor(NULL, IDC_WAIT));

            depth = 1;

            // if "appointments" tab, carefully construct the previous in history
            if (lParam == 0) {
                History[0].data.ID = 0;
                StringCchCopy(History[0].data.szPrimaryText, 
                    PRIMARY_TEXT_LENGTH, 
                    pSettings->allappointments_string);
            }
            // if "agenda" tab, carefully construct the previous in history
            else if (lParam == 2) {
                History[0].data.ID = 0;
                StringCchCopy(History[0].data.szPrimaryText, 
                    PRIMARY_TEXT_LENGTH, 
                    pSettings->favorite_category);
            }
// TODO: check this absolutely
// I'm not really sure about "History" thing
			else if (lParam == 1) { //tasks
				History[0].data.ID = 0;  //???? - changed from 0, but wtf????
				StringCchCopy(History[0].data.szPrimaryText, 
					PRIMARY_TEXT_LENGTH, 
					pSettings->alltasks_string);
			}
//allelimo

            else {
                History[0].data.ID = 0;
                History[0].data.szPrimaryText[0] = 0;
            }
            History[0].screen = Screens[lParam].parent;
            History[0].scrolled = 0;
            History[0].selectedIndex = -1;

            History[1].screen = lParam;
            History[1].scrolled = -rListHeight;
            History[1].selectedIndex = -1;

            nHighlightedTab = nCurrentTab = lParam;
            bScrolling = false;
            bDragging = false;

            parent = depth > 0 ? &History[depth-1].data : NULL;
            ListLoad(parent, Screens[History[depth].screen],
               pSettings, true);
            CalculateHeights();

			// todo: check this, 0.93 (allelimo)
            if (nCurrentTab == 1 && isPoomTainted//isRecentsTainted 
					|| nCurrentTab == 2 && isPoomTainted
					|| nCurrentTab == 0 && isPoomTainted)//isFavoritesTainted)
			{
                PostMessage(hWnd, WM_COMMAND, CMD_RELOAD, NULL);
            }

            SetCursor(NULL);

            if (History[depth].scrolled < minScrolled)
                ScrollTo(hWnd, minScrolled);
            if (bTransitioning)
                dwTransitionStart = ::GetTickCount();

            break;

        case CMD_RELOAD:
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            ReloadThread((LPVOID)hWnd);
				//HANDLE hThread = CreateThread(NULL, NULL,
				//    (LPTHREAD_START_ROUTINE)ReloadThread, (LPVOID)hWnd, NULL, NULL);
				//SetThreadPriority(hThread, THREAD_PRIORITY_BELOW_NORMAL);

				// todo: check this, 0.93 (allelimo)
				/*if (History[depth].screen == 1) 
					isRecentsTainted = false;

					else if (History[depth].screen == 2)*/
			isPoomTainted = false; //4/14/10
					//else 
					//if (History[depth].screen <0)
					//isPoomTainted = true;  //ajige
					//ajige isFavoritesTainted = false;

            SetCursor(NULL);
            break;

        case CMD_REFRESH:
            CalculateHeights();

            if (History[depth].scrolled < minScrolled)
                ScrollTo(hWnd, minScrolled);
            if (History[depth].scrolled > maxScrolled)
                ScrollTo(hWnd, maxScrolled);
            break;

		case CMD_COMPLETE:  //ajige 1/20/10
			
			if (!CanSelectItem(lParam))
                break;
			dItem = SelectItem(lParam);
			//ok
			
			if (dItem.isTask)
			{
					//IFolder *                   pCurrFldr;
					//IPOutlookItemCollection *   pItemCol;
					//HRESULT   hr       = 0;
				if (polApp == NULL) 
				{
					hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
										  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
					CHR(hr);			    
					hWnd = FindWindow (SZ_APP_NAME, NULL);
					hr = polApp->Logon((long)hWnd);
					CHR(hr);
				}
				hr = S_OK;

				Error:
						//RELEASE_OBJ(pItem);//ajige moved 
						//RELEASE_OBJ(pFolder);//ajige moved 
					if (FAILED(hr)) {
						// If we failed to log on, don't keep the object around
						RELEASE_OBJ(polApp);
					}
					int oid = dItem.oId;
					if (oid == -1)
						return E_INVALIDARG;
					
					hr = polApp->GetItemFromOid((CEOID)dItem.oId, (IDispatch**)&pTask);
					CHR(hr);
												
					if (dItem.isComplete)
					{
							hr=pTask->put_Complete(VARIANT_FALSE); 
							CHR(hr);
					}
					else
					{
						hr=pTask->put_Complete(VARIANT_TRUE);  //or -1
						CHR(hr);
					}
					hr=pTask->Save();
					CHR(hr);
						//if (dItem.isComplete)
						//	dItem.isComplete=false;
						//else
						//	dItem.isComplete;
					dItem.isComplete = !dItem.isComplete;//true;
						//MessageBox(0, TEXT("Reload"), L"Test Complete", 0);
						//if screen task, doesn't work, agenda works?????
					isPoomTainted=true;
					
						//GetClientRect(hWnd,&rList);
						//HDC GetDC(HWND hWnd);
						//InvalidateRect(hWnd,&rList,true);
						//InvalidateRect(hWnd,NULL,true);
						//UpdateWindow(hWnd);
						//PostMessage(hWnd, WM_COMMAND, CMD_REFRESH, NULL);
					
							//SetRedraw(TRUE);
						//BeginPaint(hWnd,0);
						//PostMessage(hWnd, WM_COMMAND, CMD_RELOAD, NULL);				
			}
            break;

		case CMD_EDIT_ITEM:
			//MessageBox(0,L"edit",L"",0);
			if (!CanSelectItem(lParam))
                break;
			//PostMessage(hWnd, WM_COMMAND, CMD_FORWARD, 5);
            //parent = &History[depth++].data;
			//ListLoad(parent, Screens[History[depth].screen],
              // pSettings, true);

            diEdit = SelectItem(lParam);

            x = (float)ptMouseDown.x / rList.right;
            newScreen = History[depth].screen;
           hr = Screens[newScreen].fnClick(Screens[newScreen],&diEdit, x, &newScreen, pSettings);
			//hr =Screens[5].fnPopulate(newScreen,&diEdit,NULL,pSettings);
				//if (!lParam) {
				//SendMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, 5);
			
		   if (SUCCEEDED(hr)) 
			{
                // "back"
                if (newScreen == -1) {
					
                    if (pSettings->doExitOnAction  && bSet==false) {
                        DestroyWindow(hWnd);
                    }
                    else {
                        PostMessage(hWnd, WM_COMMAND, CMD_BACK, EXPAND_DETAILS_PERIOD);
                    }
                }
                // action is done, get outta here
                else if (newScreen == -2) {
					
                    if (pSettings->doExitOnAction  && bSet==false) {
                        DestroyWindow(hWnd);
                    }
                    else {
                        PostMessage(hWnd, WM_COMMAND, CMD_REFRESH, NULL);
                    }
                }

                // "back" but upon deactivation
                  else if (newScreen == -3) {
                    bBackOnDeactivate = true;
                }

                // "forward to screen x"
				 else if (newScreen != History[depth].screen) {
                    PostMessage(hWnd, WM_COMMAND, CMD_FORWARD, newScreen);
                }

                else {
                    UnselectItem();
                }
            }
		   break;

        case CMD_CLICK_ITEM:
            if (!CanSelectItem(lParam))
                break;

            dItem = SelectItem(lParam);

            x = (float)ptMouseDown.x / rList.right;

			newScreen = History[depth].screen;
            hr = Screens[newScreen].fnClick(Screens[newScreen],&dItem, x, &newScreen, pSettings);
			
            if (SUCCEEDED(hr)) 
			{
                // "back"
                if (newScreen == -1) {
					
                    if (pSettings->doExitOnAction  && bSet==false) {
                        DestroyWindow(hWnd);
                    }
                    else {
                        PostMessage(hWnd, WM_COMMAND, CMD_BACK, EXPAND_DETAILS_PERIOD);
                    }
                }

                // action is done, get outta here
                else if (newScreen == -2) {
					
                    if (pSettings->doExitOnAction  && bSet==false) {
                        DestroyWindow(hWnd);
                    }
                    else {
                        PostMessage(hWnd, WM_COMMAND, CMD_REFRESH, NULL);
                    }
                }

                // "back" but upon deactivation
                // this is used in conjunction with CreateProcess
                // to avoid funky back action before the new window shows up
                else if (newScreen == -3) {
                    bBackOnDeactivate = true;
                }

                // "forward to screen x"
				//TODO ajige 5/28: we don't have forward button, code unneccessary??
                else if (newScreen != History[depth].screen) {
                    PostMessage(hWnd, WM_COMMAND, CMD_FORWARD, newScreen);
                }

                else {
                    UnselectItem();
                }
            }
            break;

        case CMD_BACK:
            if (depth <= 0)
                break;

            SetCursor(LoadCursor(NULL, IDC_WAIT));
			depth--;
			parent = depth > 0 ? &History[depth-1].data : NULL;
				//ListLoad(parent, Screens[History[depth].screen], pSettings, true);
			
			CalculateHeights();

			if (History[depth].screen <= 2)
			{
				nHighlightedTab = nCurrentTab = History[depth].screen;
					//BitBlt(hdcMem, rContent.left, rContent.top, width2, rHeight, 
					//     hdcPage1, width1, rContent.top, SRCCOPY);
				PostMessage(hWnd, WM_COMMAND, CMD_SWITCH_TAB, nHighlightedTab); //ajige 5/19 to avoid reload of list
				//however!! it will be reloaded if the date on the agenda is not todays
			}
			else if (History[depth].screen == 3)
			{
				nHighlightedTab = nCurrentTab = 2;
				PostMessage(hWnd, WM_COMMAND, CMD_RELOAD, 0); //ajige 5/14 added instead of ListLoad
			}
			StartTransition(hWnd, ttSlideRight, (int)lParam);//,NULL);
			
            SetCursor(NULL);
            break;

        case CMD_FORWARD:  //TODO ajige 5/28 unneccessary???
            if (depth > 2 || GetCurrentItemIndex() == -1)
                break;

            // store the selected item in History
            memcpy(&History[depth].data, &GetCurrentItem(), sizeof(DataItem));

            parent = &History[depth++].data;

            //TODO: ? History[depth].data = ??
            History[depth].screen = lParam;
            History[depth].scrolled = 0;
            History[depth].selectedIndex = -1;

            ListLoad(parent, Screens[History[depth].screen], pSettings);
            CalculateHeights();

            if (History[depth].screen <= 2)
                nHighlightedTab = nCurrentTab = History[depth].screen;

            StartTransition(hWnd, ttSlideLeft, EXPAND_DETAILS_PERIOD);//,NULL);
            break;

        case CMD_ADD:
            if (Screens[History[depth].screen].fnAdd != NULL)
                Screens[History[depth].screen].fnAdd(Screens[History[depth].screen]);//ajige added Screens[History[depth].screen]
            break;
        
        case CMD_FAVORITE: //TODO ??
            if (Screens[History[depth].screen].fnToggleFavorite == NULL)
                break;

            SetCursor(LoadCursor(NULL, IDC_WAIT));
            Screens[History[depth].screen].fnToggleFavorite(Screens[History[depth].screen], //ajige added Screens[History[depth].screen]
                &History[depth-1].data, pSettings);
            SetCursor(NULL);

            // Switch back to list of favorites, if they just
            // de-favorited one of them. Presumably, the one they
            // just favorited will be missing from the list now.
            if (nCurrentTab == 0) {
                PostMessage(hWnd, WM_COMMAND, CMD_BACK, EXPAND_DETAILS_PERIOD);
            }
            break;

		case CMD_JUMP_TO: //TODO ??
			if (lParam == 0)
				break;

			// This should only work from the "All Contacts" screen.
			if (History[depth].screen != 2)
				break;

			// We can only jump if we recognize the letter.
			pLetter = _tcschr(alphabet, (TCHAR)lParam);
			if (pLetter == 0)
				break;

			UnselectItem();
			ScrollTo(hWnd, GroupPosition[pLetter - alphabet]);

			break;
    }

    InvalidateRect(hWnd, &rScreen, FALSE);
    UpdateWindow(hWnd);

    return 0;
}

//-----------------------------------------------------------------------------
// DoDestroyMain - Process WM_DESTROY message for window
//
LRESULT DoDestroyMain (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam) {
   
    // Uninitialize the COM classes
    CoUninitialize();

    // Clean up HREGNOTIFY's
    for (int i = 0; i < HR_NOTIFY_COUNT; i++) {
        if (NULL != hrNotify[i]) {
            RegistryCloseNotification(hrNotify[i]);
            hrNotify[i] = 0;
        }
    }

    // Clean up titlebar
	if (pSettings->doShowFullScreen)
	    DestroyTitlebar();

	// Clean up sensors
	if (pSettings->doEnableSensor) {
		SensorGestureUninit();
		SensorPollingUninit();
	}

    // Quit
    PostQuitMessage (0);
    return 0;
}

//-----------------------------------------------------------------------------
// Screen Drawing Functions
//
void DrawScreenOn(HDC hdc, RECT rClip, HDC hdcTmp, int yListOffset) {

    RECT rect;
	
	// MAIN CONTENT
    if (Screens[History[depth].screen].hasMenus) {
        IntersectRect(&rect, &rList, &rClip);
        if (!IsRectEmpty(&rect))
            DrawContentOn(hdc, rect, hdcTmp, yListOffset);

		IntersectRect(&rect, &rMenubar, &rClip);
		if (!IsRectEmpty(&rect))
			DrawMenubarOn(hdc);
	}

    else //details screen
	{
RECT rItem;//expansion

	rItem.bottom = rContent.top - yListOffset;	

	IntersectRect(&rect, &rContent, &rClip);
		
		if (!IsRectEmpty(&rect))
			DrawContentOn(hdc, rect, hdcTmp, yListOffset);//yListOffset);		
		
	}//details screen

    // TITLE BAR
    IntersectRect(&rect, &rTitlebar, &rClip);
    if (!IsRectEmpty(&rect))
	    DrawTitlebarOn(hdc, rTitlebar, hdcSkin, TitlebarFont, szWindowTitle);

    // HEADER BAR
    IntersectRect(&rect, &rHeader, &rClip);
    if (!IsRectEmpty(&rect))
        DrawHeaderOn(hdc, rHeader, hdcSkin);	
}


/*//5/5/10 not neccessary
void DrawExpanded(HDC hdc, RECT rect)//rClip)
{	//if(Screens[History[depth].screen].hgScreen==4)
	//{
	//MessageBox(0,L"DrawExpanded",L"",0);

			for (int i = 0; i < ARRAYSIZE(TaskEdits); i++) 
			{
				SingleEdit ss = TaskEdits[i];
				TCHAR * value = EditValuesT[i];

				 // calculate rItem
				rect.top = rect.bottom;
				rect.bottom = rect.top+ SCALE(DEFAULT_ITEM_HEIGHT);
					   //     rect.left = rContent.left;
						//    rect.right = rContent.right;
							//DrawRect(hdc, &rect, GetSkinRGB(SKIN_COLOR_LIST_ITEM_BACKGROUND));
				int baseline = rect.bottom - (SCALE(DEFAULT_ITEM_HEIGHT - ITEM_FONT_SIZE) / 2);
						// draw separator
							  //  RECT rSep = rect;
								//rSep.top = rect.bottom - SCALE(LIST_SEPARATOR_HEIGHT);
								//DrawRect(hdc, &rSep, GetSkinRGB(SKIN_COLOR_LIST_ITEM_SEPARATOR));
						      
								// draw caption
							   // SetTextAlign(hdc, TA_LEFT | TA_BOTTOM);
				SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
						//ExtTextOut(hdc, rect.left + SCALE(LIST_ITEM_INDENT), baseline, 
						//	ETO_CLIPPED, &rect, ss.caption, _tcslen(ss.caption), NULL);

				// draw setting
				switch (ss.type) 
				{			
					case stList:
							//MessageBox(0,L"stList",L"",0);
							//hWnd = FindWindow (SZ_APP_NAME, NULL);
							// GetClientRect(hWnd, &rect); 
							//InvalidateRect(hWnd, &rect, true);
							//InvalidateRect(hWnd, NULL, TRUE);     
						DrawValue(hdc, rect, value);//this stays on during scroll, and when selecting new item details
							//DrawContentOn(hdc,rect,hdc,yListOffset);
						UnselectItem();
						break;
					case stOnOff:
					  //  DrawOnOff(hdc, rect, value[0] == '0' ? false : true);
						break;
				}
				//if this item is selected, draw the details
				if (nExpandedIndex == i && ss.type == stList) 
				{
					int rPartialHeight = trTransitionType == ttExpand
					? (int)(dTransitionPct * rExpandedHeight)
						: (int)((1.0 - dTransitionPct) * rExpandedHeight);

					rect.top = rect.bottom;
					rect.bottom += rPartialHeight;
					rect.left = SCALE(LIST_ITEM_INDENT);
					rect.right -= rect.left;

					//RECT rItemClip;
					//IntersectRect(&rItemClip, &rect, &rClip);

					//DrawListDetailsOn(hdc, rect, rItemClip, value);
				}
			}//for
		//}	//edit screen
}*/
/*
//5/5/10 not neccessary 4/15/10 for edit
void DrawListDetailsOn(HDC hdc, RECT rect, RECT rClip, const TCHAR * tszValue)//, HDC hdcTmp, int yListOffset) 
{
//this should be moved to Drawcontent on
	RECT rItemClip;
	RECT rItem = rect;
	rItem.bottom = rect.bottom - rExpandedHeight;

	int indent = SCALE(LIST_ITEM_INDENT);
	int height = SCALE(DEFAULT_ITEM_HEIGHT);
	int padding = SCALE(ITEM_DETAILS_PADDING);

	DrawRect(hdc, &rClip, GetSkinRGB(SKIN_COLOR_LIST_ITEM_SEPARATOR));//expanded list background
	HFONT hfOld = (HFONT)SelectObject(hdc, PrimaryListFont);
	SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
	SetTextAlign(hdc, TA_LEFT | TA_TOP);
	
	for (int j = 0; j < nOptions; j++) 
	{
		rItem.top = rItem.bottom;
		rItem.bottom += height;
			//OffsetRect(&rItem,0,100);nothing
			//OffsetRect(&rClip,0,100); no text
			//OffsetRect(&rect,0,100); no change
		IntersectRect(&rItemClip, &rItem, &rClip);
			//no text IntersectRect(&rect, &rItem, &rClip);
			//IntersectRect(&rect,&rItem,&rClip);
			//DrawListDetailsOn(hdc, rItem, rect, value);
		if (IsRectEmpty(&rItemClip))
			continue;
		ExtTextOut(hdc, rItem.left + indent * 2, rItem.top + indent,
			ETO_CLIPPED, &rItemClip,
				//L"ExpansionTest", _tcslen(L"ExpansionTest"), NULL);
			EditOptions[j], _tcslen(EditOptions[j]), NULL);
		
		if (0 == _tcscmp(tszValue, EditOptions[j])
			|| _tcslen(tszValue) == 0
			&& _tcsstr(EditOptions[j], SZ_AUTO) == EditOptions[j]) 
		{	
				int radius = indent / 2;
				Ellipse(hdc, 
					rItem.left + indent - radius,
					rItem.top + height / 2 - radius,
					rect.left + indent + radius,
					rItem.top + height / 2 + radius);
		}
	}

	SelectObject(hdc, hfOld);
}*/
/*
//5/5/10 not neccessary 4/15/10 for edit
void ExpandIt(HWND hWnd, int index) {
		//TCHAR newItem[MAX_PATH] = {0};
		//wsprintf(newItem, TEXT("%i"), index);
		//MessageBox(0,L"expandit",newItem,0);
		//if (!CanSelectItem(index))
		//			        return ;
	
	DataItem dItem = SelectItem(index);
	if (dItem.isTask)
	{
		nOptions = TaskEdits[index].filler(EditOptions, EditValuesT[index]);
		}
	else
	{
		nOptions = AppEdits[index].filler(EditOptions, EditValuesA[index]);
	}
	bExpanded=true;//4/22/10
	nExpandedIndex = index;
	rExpandedHeight = nOptions * SCALE(DEFAULT_ITEM_HEIGHT);
	//TODO height for Notes should be calculated based on Drawtext
	//for inline expansion: StartTransition(hWnd, ttExpand, 150);//,NULL);
	StartTransition(hWnd, ttEditExpand, 150);//,NULL); 5/3/10
		//index=-1;
}
*/
void DrawContentOn(HDC hdc, RECT rect, HDC hdcTmp, int yOffset) {
	int         nFirstItem, nItem;
    DataItem    dItemTmp;
    TCHAR       buffer[SECONDARY_TEXT_LENGTH];
    int         count = GetItemCount();
    int         currentItemIndex = GetCurrentItemIndex();
    bool        canGetGroup = NULL != Screens[History[depth].screen].fnGetGroup;
    RECT        rItem = rList;
    int         ryOffset = yOffset + rect.top - rContent.top;
	// removed from here code for bitmap (contact photo)

#ifdef DEBUG_GRAPHICS_SPEED
	DWORD tTime1, tTime2, tTime3, tTime4, tTime5, tTime6;
	tTime1 = ::GetTickCount();
#endif

	// ******* draw list background (if any) that appears above the list items

    if (ryOffset < 0) {
        rItem.bottom = rect.top - ryOffset;
		DrawCanvasOn(hdc, rItem);
    }

#ifdef DEBUG_GRAPHICS_SPEED
	tTime2 = ::GetTickCount();
#endif

	SetBkMode(hdc, TRANSPARENT);

    // now start drawing the content
	// special case for 0 list items
	if (count == 0) 
	{
		rItem.bottom = rItem.top;
	}

	else 
	{
		// We want to draw all items, but for performance reasons,
		// there's no need to draw any items that are beyond the 
		// top of the screen. So determine the first visible item.
		nFirstItem = nItem = ryOffset <= 0 ? 0 : GetPixelToItem(ryOffset);
		rItem.bottom = rect.top + GetStartPosition(nItem) - ryOffset;

#ifdef DEBUG_GRAPHICS_SPEED
	tTime3 = ::GetTickCount();
#endif


		// ******* DRAW LIST ITEMS
		while (nItem < count && rItem.bottom < rect.bottom) 
		{
			dItemTmp = GetItem(nItem);

			rItem.top = rItem.bottom;

			// This is for detecting if we have the start of a type group
			// (a bunch of diPhone, or diEmail, etc.)
			if (IsItemNewType(nItem)) 
			{
				int itemheight = SCALE(DEFAULT_ITEM_HEIGHT);
				int limit = 1 + (rect.bottom - rItem.top) / itemheight;
				int sametype = CountSameTypeAs(nItem, limit);
				rItem.bottom += GetStartPosition(nItem + sametype) 
					- GetStartPosition(nItem);
				DrawItemBackgroundOn(hdc, dItemTmp.type, rItem, rect);
					//4/15/10 tried: rect.left=rect.left+100;=>messes everything up
			}

			// special case: draw the background starting with one above
			// the first visible item, for proper "rounded corners" effect
			else if (nItem == nFirstItem) 
			{				
				int limit = 1 + (rect.bottom - rItem.top) 
					/ SCALE(DEFAULT_ITEM_HEIGHT);
				int sametype = CountSameTypeAs(nItem, limit);
				rItem.bottom += GetStartPosition(nItem + sametype) 
					- GetStartPosition(nItem);
				rItem.bottom = min(rItem.bottom, rect.bottom);

				int offset = GetItemHeight(nItem - 1);
				rItem.top -= offset;
					//4/15/10 tried below, no change
					//rect.left=rect.left+100; 
					//rItem.left=rItem.left+100;
				DrawItemBackgroundOn(hdc, dItemTmp.type, rItem, rect);
				rItem.top += offset;
			}

			rItem.bottom = rItem.top + GetItemHeight(nItem);

			if (nItem == currentItemIndex && !bMouseDown) 
			{
				rClickRegion = rItem;
			}
			DrawItemOn(hdc, dItemTmp, rItem);

			rItem.left = rList.left;

			// ****** Group Header
			if (dItemTmp.iGroup 
				&& rItem.top >= rect.top
				&& canGetGroup
				&& IsItemNewGroup(nItem)) 
			{
				DrawGroupHeaderOn(hdc, dItemTmp, rItem);
			} 

			//4/26 to draw the expansion on the details screen
			//however, it draws the details below the value, not on top

		/*	//5/5/10 not neccessary??
		SingleEdit ss = TaskEdits[nItem];
			TCHAR * value = EditValuesT[nItem];
			RECT rExpand;
			
				//rItem.bottom=rContent.top+nItem*SCALE(DEFAULT_ITEM_HEIGHT)+50;
				//RECT rItem;
				//rect.top=rect.top-SCALE(DEFAULT_ITEM_HEIGHT);
				//if this item is selected, draw the details
			if (nExpandedIndex == nItem && ss.type == stList) 
			{
				int rPartialHeight = trTransitionType == ttExpand
				? (int)(dTransitionPct * rExpandedHeight)
					: (int)((1.0 - dTransitionPct) * rExpandedHeight);
					//int offset = GetItemHeight(nItem - 1);
					//rItem.top -= offset;
					//rItem.bottom=rContent.top-Offset;
					// rItem.bottom = rect.top - ryOffset;
					//rItem.top=rect.top-ryOffset;
					//rItem.top=rItem.bottom - SCALE(DEFAULT_ITEM_HEIGHT);// - ITEM_FONT_SIZE) / 2);
					//sort of ok rItem.bottom = rect.top + GetStartPosition(nItem)+SCALE(DEFAULT_GROUP_HEIGHT);// - ryOffset;
				rItem.top = rItem.bottom;//-SCALE(DEFAULT_ITEM_HEIGHT);
				rItem.bottom += rPartialHeight;
					//rItem.bottom -=SCALE(DEFAULT_ITEM_HEIGHT);
					//rItem.top=rItem.top+SCALE(DEFAULT_GROUP_HEIGHT);
				rItem.left = SCALE(LIST_ITEM_INDENT);
				rItem.right -= rItem.left;
					//rect.top=100;
					//IntersectRect(&rect,&rItem,&rExpand);
				IntersectRect(&rExpand,&rItem,&rect);
				//MessageBox(0,value,dItemTmp.szPrimaryText,0);
				if (!IsRectEmpty(&rExpand))
					 DrawListDetailsOn(hdc, rItem, rExpand, dItemTmp.szPrimaryText);//value);//,hdcTmp, yListOffset);		
					//sort of ok rItem.bottom += SCALE(DEFAULT_ITEM_HEIGHT);
				//to reset margins for main list:
				rItem.left -= SCALE(LIST_ITEM_INDENT);
				rItem.right =rect.right;
				
			}//if selected*/

			//4/26

			// Next nItem
			nItem++;
		}//while
	} //else (count!= 0)

#ifdef DEBUG_GRAPHICS_SPEED
    tTime4 = ::GetTickCount();
#endif

    // draw the list background (if any) that appears below the list
    // Also, now the "about" text might be visible
    if (rItem.bottom < rect.bottom) {
        rItem.top = rItem.bottom;
        rItem.bottom = rect.bottom;
		DrawCanvasOn(hdc, rItem);
        
        // "About" at bottom of screen
        SelectObject(hdc, SecondaryListFont);
        SetTextAlign(hdc, TA_LEFT | TA_BOTTOM);
        SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_HEADER_LOADING_TEXT));
        int y = Screens[History[depth].screen].hasMenus 
            ? rList.bottom - 2 : rContent.bottom - 2;
        ExtTextOut(hdc, rContent.left + 2, y, 
            ETO_CLIPPED, &rItem, SZ_ABOUT, _tcslen(SZ_ABOUT), 0);
    }

	if (count == 0)
		return;

	// Special: Draw the group of the list nItem that's at the top of the list
	dItemTmp = GetItem(nFirstItem);
	if (dItemTmp.iGroup && yOffset >= 0 && canGetGroup) {

		int nHeight = SCALE(DEFAULT_GROUP_HEIGHT);
		int nBottom = nHeight;

		RECT rTopGroup = {rContent.left, 0, rContent.right, nHeight};
		DrawGroupHeaderOn(hdcTmp, dItemTmp, rTopGroup);

		if (nFirstItem < count - 1 && IsItemNewGroup(nFirstItem + 1)) {
			nBottom = min(nBottom, GetStartPosition(nFirstItem + 1) - yOffset);
		}

		// account for the fact that the list
		// doesn't start at the top of the screen
		nBottom += rContent.top;

		int nLeft = rContent.left;
		int nWidth = rContent.right - rContent.left;
		int nTop = nBottom - nHeight;

		if (bScrolling && pSettings->doFastGraphics) {
			BitBlt(hdc, nLeft, nTop, nWidth, nHeight, hdcTmp, 0, 0, SRCCOPY);
		}
		else {
			BltAlpha(hdc, nLeft, nTop, nWidth, nHeight, hdcTmp, 200);
		}
	}

#ifdef DEBUG_GRAPHICS_SPEED
    tTime5 = ::GetTickCount();
#endif

    // Draw list indicator if scrolling
	if (bScrolling 
		&& (Velocity < -0.1 || Velocity > 0.1) 
		&& canGetGroup 
		&& Screens[History[depth].screen].hgScreen<4  //doesn't make sense on the details list4/21/10
		) 
	{
		SelectObject(hdc, ListIndicatorFont);
	    SetTextAlign(hdc, TA_CENTER);
		//SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
		SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_DETAIL_MAIN_SHADOW));
		SetBkMode(hdc, TRANSPARENT);

        // dItemTmp is set previously to the first item
        Screens[History[depth].screen].fnGetGroup(Screens[History[depth].screen], //ajige
            &dItemTmp, buffer, SECONDARY_TEXT_LENGTH, pSettings);

        ExtTextOut(hdc, (rContent.right + rContent.left) / 2, 
            rContent.top + 10, NULL, NULL, buffer, _tcslen(buffer), 0);
	}

	// If scrolling, draw a scrollbar
	if ((bScrolling || bDragging) && ListHeight) {
		int screenh = Screens[History[depth].screen].hasMenus 
			? rList.bottom - rList.top 
			: rContent.bottom - rContent.top;

		int height = MulDiv(screenh, screenh, ListHeight);
		int top = MulDiv(screenh, History[depth].scrolled, ListHeight);

		RECT rScrollbar;
		rScrollbar.right = rList.right - SCALE(1);
		rScrollbar.left = rScrollbar.right - SCALE(2);
		rScrollbar.top = top + rContent.top;
		rScrollbar.bottom = rScrollbar.top + height;
		DrawRect(hdc, &rScrollbar, GetSkinRGB(SKIN_COLOR_SCROLLBAR));
	}

#ifdef DEBUG_GRAPHICS_SPEED
	tTime6 = ::GetTickCount();
	DEBUGMSG(1, (TEXT("2:%d, 3:%d, 4:%d, 5:%d, 6:%d"), tTime2-tTime1, tTime3-tTime2, tTime4-tTime3, tTime5-tTime4, tTime6-tTime5));
#endif

}

void DrawMenubarOn(HDC hdc) {
    // MENU BAR
    int rMenubarWidth = rMenubar.right - rMenubar.left;

	// this is only necessary if in landscape mode
	if (rMenubarWidth > SCALE(DEFAULT_SCREEN_WIDTH)) {
		// Copy the first (1 * vga) columns of the 
		// menu bar from skin to memory
		BitBlt(hdc, 0, rMenubar.top,
			SCALE(1), SCALE(SKIN_MENU_BAR_Y_OFFSET),
			hdcSkin, 0, SCALE(SKIN_MENU_BAR_HEIGHT), SRCCOPY);

		// This will copy the first (1 * vga) columns of 
		// the menu bar fully across the screen
		for (int x = SCALE(1); x < rMenubarWidth; x *= 2) {
			int w = 2 * x > rMenubarWidth ? rMenubarWidth - x : x;
			BitBlt(hdc, x, rMenubar.top, w, SCALE(SKIN_MENU_BAR_HEIGHT),
				hdc, 0, rMenubar.top, SRCCOPY);
		}
	}

    // figure out the highlighted tab
    int tab = bMouseDown && ptMouseDown.y > rMenubar.top 
        ? ptMouseDown.x * 5 / rMenubarWidth : nHighlightedTab;

    // draw buttons
	for (int i = 0; i < 5; i++) {
		int xdest = rMenubar.left 
			+ rMenubarWidth / 10 * (2 * i + 1) 
			- SCALE(MENU_BAR_ICON_WIDTH) / 2;
		int ydest = rMenubar.top;
		int xsrc = i * SCALE(SKIN_MENU_BAR_ICON_WIDTH);
		int ysrc = i == tab 
			? SCALE(SKIN_MENU_BAR_SEL_Y_OFFSET) 
			: SCALE(SKIN_MENU_BAR_Y_OFFSET);
		BitBlt(hdc, xdest, ydest,
			SCALE(MENU_BAR_ICON_WIDTH),
			SCALE(SKIN_MENU_BAR_HEIGHT), 
			hdcSkin, xsrc, ysrc, SRCCOPY);
    }

	RECT rect;
	rect.left = 2 * SCALE(SKIN_MENU_BAR_ICON_WIDTH) + 4; //allelimo: changed this to center the number ???
	rect.top = rMenubar.top;
	rect.bottom = rMenubar.bottom;
	rect.right = rect.left + SCALE(SKIN_MENU_BAR_ICON_WIDTH);
	TCHAR buf[3];
	wsprintf(buf, TEXT("%d"), stToday.wDay);
	
	SelectObject(hdc, SecondaryListFont);	//allelimo: a smaller font
	SetTextAlign(hdc, TA_CENTER);
	SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));	//4/22/10
	//SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_MISSED));	//red - only to see it better while testing :)
	SetBkMode(hdc, TRANSPARENT);


	ExtTextOut(hdc, 
		rect.left + SCALE(SKIN_MENU_BAR_ICON_WIDTH) * 2 / 5, 
		rect.bottom - SCALE(SKIN_HEADER_HEIGHT) + 1, 0,  //ajige
		&rect, buf, _tcslen(buf), 0);

	//allelimo:
	/*
	now the date is drawn ok when the agenda tab is not selected.
	when the agenda tab is selected, we should shift it up following the skin design, and this could be
	done using the int tab on line 2181 BUT then if a skin does not shift the calendar icon up the date will be
	drawn incorrectly again...
	what do you think ?
	*/
}

void DrawGroupHeaderOn(HDC hdc, DataItem dItem, RECT rItem) {
    RECT rHeader = rItem;
	rHeader.bottom = rHeader.top + SCALE(DEFAULT_GROUP_HEIGHT);
    TCHAR buffer[SECONDARY_TEXT_LENGTH];
    Screens[History[depth].screen].fnGetGroup(Screens[History[depth].screen], //ajige
        &dItem, buffer, SECONDARY_TEXT_LENGTH, pSettings);
    int length = _tcslen(buffer);

	// ****** GroupHeader background
	DrawRect(hdc, &rHeader, GetSkinRGB(SKIN_COLOR_LIST_GROUP_BACKGROUND));

    // separator
    RECT rSep = rHeader;
	rSep.top = rHeader.bottom - SCALE(LIST_SEPARATOR_HEIGHT);
    DrawRect(hdc, &rSep, GetSkinRGB(SKIN_COLOR_LIST_ITEM_SEPARATOR));
	SetTextAlign(hdc, TA_LEFT);

	// ******* Draw Group Header Text
	SelectObject(hdc, GroupFont);
   	SetBkMode(hdc, TRANSPARENT);
	SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_GROUP_TEXT));
	ExtTextOut(hdc, rItem.left + SCALE(LIST_GROUP_ITEM_INDENT),
		rHeader.top - 1 
		+ SCALE(DEFAULT_GROUP_HEIGHT - GROUP_ITEM_FONT_SIZE) / 2,
		NULL, NULL, buffer, length, 0);
}

void DrawItemBackgroundOn(HDC hdc, DataItemType diType, RECT rect, RECT rClip) {
	RECT rIntersect;
	IntersectRect(&rIntersect, &rect, &rClip);
/* if edit screen is treated as a list

if (diType==diListItem
		||diType==diSubject)//Info
		//||diType==diStatus)
			DrawRect(hdc, &rIntersect, GetSkinRGB(SKIN_COLOR_LIST_ITEM_BACKGROUND));
	else
	{
		// Draw the canvas
			DrawCanvasOn(hdc, rIntersect);

            // Draw the button background
            // TODO: make the button prettier
			SelectObject(hdc, CreateSolidBrush(GetSkinRGB(
				SKIN_COLOR_LIST_ITEM_BACKGROUND)));
				
			int padding = SCALE(ITEM_DETAILS_PADDING);
			SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
           //rect.left=SCALE(64);//4/15/10 to avoid labels being inside the box.
				RoundRect(hdc, 
					rect.left + padding / 2, 
					rect.top + padding / 3, 
					rect.right - padding / 2, 
					rect.bottom - padding / 3,
					padding, padding);
	}
	
*/
		switch (diType) { 
				//4/14/10 to prepare for the edit
				//all items should look like buttons, so clicking will edit
			case diListItem:
					// Item Background
				DrawRect(hdc, &rIntersect, GetSkinRGB(SKIN_COLOR_LIST_ITEM_BACKGROUND));
				break;
						//ajige 5/29: changed drawing so only the ones that can be clicked on has button look  
					//case diNothing:
						//ajige 5/29 case diSubject:
					//case diDateTime:
					//case diLocation: 
					//case diCategory:
					//case diStatus:
						// Just draw the canvas
						//DrawCanvasOn(hdc, rect);
						//break;
					
					// button look
					//case diDateTime:
					//case diCategory:
					//case diStatus:
					// buttons
					//case diSubject:  //ajige 5/28
			
			//case diDetailsButton:
						
			case diEditButton:
				rect.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;
					//case diSaveContactButton:
			default:// 4/29/10 they should all be clickable, except complete, and all day
					//int slen = _tcslen(dItem.szPrimaryText);
					//if (slen > 0) {

					// Draw the canvas
				DrawCanvasOn(hdc, rIntersect);

					// Draw the button background
					// TODO: make the button prettier
				SelectObject(hdc, CreateSolidBrush(GetSkinRGB(
					SKIN_COLOR_LIST_ITEM_BACKGROUND)));
					
				int padding = SCALE(ITEM_DETAILS_PADDING);
				SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
				rect.left  +=SCALE(DEFAULT_SCREEN_WIDTH)/3;	
				RoundRect(hdc, 
						rect.left + padding / 2, 
						rect.top + padding / 3, 
						rect.right - padding / 2, 
						rect.bottom - padding / 3,
						padding, padding);
				rect.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;
			//}
			//else
			//	DrawCanvasOn(hdc, rect);


            break;
}
}

void DrawItemOn(HDC hdc, DataItem dItem, RECT rItem) {
    RECT rClip, rSep, rClip2;
		//    SIZE textSize;
    int  slen; //y, 4/15/10
    COLORREF color;
	LPTSTR lpStr;  // will hold the "ellipsis-terminated" string
	
	int padding = SCALE(ITEM_DETAILS_PADDING);
	int one = SCALE(1);
	int nIconWidth = SCALE(MENU_BAR_ICON_WIDTH);
	int nHeaderHeight = SCALE(SKIN_HEADER_HEIGHT);
	int nYOffset = SCALE(SKIN_HEADER_Y_OFFSET);
	int height=0; //5/2/10
	rClip.left = rItem.left + padding / 2 + one;
	rClip.right = rItem.right - padding / 2 - one;
	rClip.top = rItem.top + padding / 2 + one;
	rClip.bottom = rItem.bottom - padding / 2 - one;

		//test for (allelimo)
	rClip2 = rClip;
		//rClip2.left=rClip.left;//+SCALE(64);
		//rClip2.top=rClip.top;
	rClip2.bottom = rClip.bottom + (rClip.bottom - rClip.top)* 2;
	SelectObject(hdc, MainListFont);

    switch (dItem.type) {
		case diListItem:
            // separator
            rSep = rItem;
			rSep.top = rItem.bottom - SCALE(LIST_SEPARATOR_HEIGHT);
            DrawRect(hdc, &rSep, GetSkinRGB(SKIN_COLOR_LIST_ITEM_SEPARATOR));
            // Item Primary Text
	        SetTextAlign(hdc, TA_LEFT);
	        SelectObject(hdc, MainListFont);  //allelimo: mainlistfont is smaller than original font, only for appointments list
            color = GetSkinRGB(//dItem.isFavorite && nCurrentTab != 0 //ajige removed
                //? SKIN_COLOR_LIST_ITEM_FAVORITE //ajige  removed
                //: //ajige removed see below
				dItem.isOverdue ? SKIN_COLOR_LIST_ITEM_MISSED
                : SKIN_COLOR_LIST_ITEM_TEXT);
			 SetTextColor(hdc, color); //ajige 5/28 mistakenly deleted in v.93, caused overdue not be drawn with correct color
			
			 // write ellipsis when needed
			lpStr = WriteEllipsis(hdc, dItem.szPrimaryText, rClip);
			 
//ajige 1/20/10
			 if(dItem.isTask==true) //ajige used for tasks to get space for a check box
			 {//TODO ajige 2/12/10 change BuildFont to include Strikeout too?
				// #define FT_STRIKE 0x2
				// DWORD dwFontFlags =0;
				 int compl=0;
				 if (dItem.isComplete==VARIANT_TRUE)	
				 {
					 compl=3;
						// dwFontFlags |= FT_STRIKE;
						// MessageBox(0, L"dItem.isComplete", SZ_APP_NAME, 0);
				 }
				 else
					 compl=2;
					// if(task complete, then compl=3)
				int nIconWidth = SCALE(MENU_BAR_ICON_WIDTH);
				int nHeaderHeight = SCALE(SKIN_HEADER_HEIGHT);
				int nYOffset = SCALE(SKIN_HEADER_Y_OFFSET);
				MainListFont=BuildFont(SCALE(MAINLIST_FONT_SIZE), FALSE, FALSE);//,dwFontFlags);
					//BuildFont(HDC hDC, HFONT hBaseFont, DWORD dwFlags);
				 ExtTextOut(hdc, rItem.left + SCALE(30), rItem.bottom - 2 
					- (SCALE(DEFAULT_ITEM_HEIGHT + ITEM_FONT_SIZE) / 2),
					ETO_OPAQUE, NULL, dItem.szPrimaryText, 
					_tcslen(dItem.szPrimaryText), 0);
								
					//code for checkbox image.
				// if (dItem.type==diListItem 
				//	 || dItem.type==diStatus)
				 {
					StretchBlt(hdc, 
					rItem.left,//x
					rItem.bottom - 2 - (SCALE(DEFAULT_ITEM_HEIGHT + ITEM_FONT_SIZE) / 2),//y
					nIconWidth/2, //w
					nHeaderHeight, //h
					hdcSkin, //source
					nIconWidth*(compl+0.4), //source x
					nYOffset, //source y
					nIconWidth/2, //source width
					nHeaderHeight,  //source height
					SRCCOPY);
				 }
			 }
			else//not task

					// allelimo: to use DrawText uncomment the following lines and comment the previous one
					//if(_tcslen(dItem.szPrimaryText)>0)
					//{
					//		//SIZE   szStr;
					//		//GetTextExtentPoint32(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), &szStr);
					//	rClip.right=rClip.right-50;//-szStr.cx;
					//}
					//DrawText(hdc,dItem.szPrimaryText,_tcslen(dItem.szPrimaryText),&rClip,DT_END_ELLIPSIS|DT_LEFT|DT_BOTTOM);
					//	if(Screens[History[depth].screen].hgScreen<4)

				ExtTextOut(hdc, rItem.left + SCALE(LIST_ITEM_INDENT), 
					rItem.bottom - 2 - SCALE(DEFAULT_ITEM_HEIGHT + ITEM_FONT_SIZE) / 2,
		            ETO_OPAQUE, NULL, lpStr, 
					_tcslen(dItem.szPrimaryText), 0);
						//else
							//DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
							//&rClip2/*&rItem*/, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
								//		&rItem, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
						//DrawText( hdc,dItem.szPrimaryText, -1, &rItem, DT_WORDBREAK | DT_CALCRECT );
							//lpMIS->itemHeight = itemHeight;

			 slen = _tcslen(dItem.szTertiaryText);
				if (slen > 0) {
					SelectObject(hdc, SecondaryListFont);
					SetTextAlign(hdc, TA_RIGHT);
					SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
					ExtTextOut(hdc, rItem.right - SCALE(LIST_ITEM_INDENT), 
						rItem.bottom - 2 //allelimo: to use DrawText must be + 3 
						- SCALE(DEFAULT_ITEM_HEIGHT + ITEM_SECONDARY_FONT_SIZE) / 2,
						ETO_OPAQUE, NULL, dItem.szTertiaryText, slen, 0);
				}

            break; //listitem

        case diSubject: //=SUBJECT
				//SelectObject(hdc, PrimaryListFont);
			SetTextAlign(hdc, TA_LEFT | TA_TOP);
				//rClip.bottom = rItem.bottom;
				//rItem.top = rItem.top  -5; //ajige 5/18
			rItem.left=rItem.left+padding; //4/22/10
			rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;			
				// Display the shadow, removed 4/29/10.
				/*if (GetSkinRGB(SKIN_COLOR_DETAIL_MAIN_SHADOW) 
					!= GetSkinRGB(SKIN_COLOR_DETAIL_MAIN_TEXT)) 
				{
					SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_DETAIL_MAIN_SHADOW));
						
					
				DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
					&rClip2//&rItem
					, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
								//	&rItem, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 							       
									// ExtTextOut(hdc, rItem.left + padding + 1, 
									//    rItem.top + padding + 1,
									//    ETO_CLIPPED, &rClip, dItem.szPrimaryText, 
									//    _tcslen(dItem.szPrimaryText), NULL);	
				
				}*/
				// Display the name
						//rItem.left=rItem.left;
			SelectObject(hdc, ItemDetailsFont);
			DrawText(hdc, pSettings->subject_string, _tcslen(pSettings->subject_string), //ajige 5/18
							&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
			SelectObject(hdc, MainListFont);
			SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_DETAIL_MAIN_TEXT));
			height=DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
				&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP|DT_CALCRECT); 
			if (height>MAINLIST_FONT_SIZE) //More than 1 line, needs to be placed further up
			{
				rClip2.top=rClip2.top-SCALE(DEFAULT_ITEM_HEIGHT)/6;//+SCALE(HEADER_HEIGHT)/2;
				DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
					&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
				rClip2.top=rClip2.top+SCALE(DEFAULT_ITEM_HEIGHT)/6;//+SCALE(HEADER_HEIGHT)/2;
				
			}
			else
					//	rClip2.top=rClip2.top+SCALE(DEFAULT_ITEM_HEIGHT)+SCALE(HEADER_HEIGHT);	
				DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
					&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
									   //ajige 4/14/10
										//SelectObject(hdc, SecondaryListFont);
				
								    
						/*ExtTextOut(hdc, rItem.left + padding, 
									rItem.top + padding,
									ETO_CLIPPED, &rClip, dItem.szPrimaryText, 
									 _tcslen(dItem.szPrimaryText), NULL);*/
            
								//4/21/21
					//rItem.bottom=rItem.bottom-12;
					//rItem.top=rItem.top-12;
					//DrawValue(hdc, rItem, dItem.szPrimaryText);
									///test 4/22/10
								//rItem.right=rItem.right-padding;
								//DrawText( hdc,L"v", _tcslen(L"v"), &rItem, DT_RIGHT );
							
							/*StretchBlt(hdc, //draws a = sign
									rItem.right -SCALE(MENU_BAR_ICON_WIDTH), rItem.top,
									SCALE(MENU_BAR_ICON_WIDTH), SCALE(SKIN_HEADER_HEIGHT),
									hdcSkin, 
									SCALE(MENU_BAR_ICON_WIDTH) * 4, SCALE(SKIN_HEADER_Y_OFFSET), 
									SCALE(MENU_BAR_ICON_WIDTH), SCALE(SKIN_HEADER_HEIGHT),
									SRCCOPY);	*/
							///
				rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;	
			break;		

			case diImportance:
				SelectObject(hdc, ItemDetailsFont);
				SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_DETAIL_MAIN_TEXT));
					//if(dItem.isTask)
				DrawText(hdc, pSettings->priority_string, _tcslen(pSettings->priority_string), 
						&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
				rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;
				SelectObject(hdc, MainListFont);
				DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), 
					&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
				rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;			
				break;	

			case diLocation:  //LOCATION
								// Display location for appointments and importance for tasks 
								//SelectObject(hdc, SecondaryListFont);
				SelectObject(hdc, ItemDetailsFont);
				SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_DETAIL_MAIN_TEXT));
									//ajige 4/14/10
									//MessageBox(0,dItem,L"",0);
						//if(dItem.isTask)
						//	DrawText(hdc, pSettings->priority_string, _tcslen(pSettings->priority_string), 
						//		&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
						//else
				DrawText(hdc, pSettings->location_string, _tcslen(pSettings->location_string), 
				&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
										//ajige 4/14/10
				rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;
				SelectObject(hdc, MainListFont);
				DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), 
					&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
				rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;					   
					//ExtTextOut(hdc, rItem.left + padding, 
					//rItem.top + padding + 1,//ajige 5/18 added padding to have text further down, to make room for wordwrap
					//NULL, NULL, dItem.szPrimaryText,
					//_tcslen(dItem.szPrimaryText), NULL);
			break;

			case diStatus:
						 //SelectObject(hdc, SecondaryListFont);
					//slen = _tcslen(dItem.szPrimaryText);
					//if (slen > 0) 
				{
					SelectObject(hdc, ItemDetailsFont);
					SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
						//SetTextAlign(hdc, TA_RIGHT | TA_BOTTOM);
							//ajige: 5/18 Y is not used.	y = (rItem.bottom + rItem.top) / 2;

						// copied from iLaunch
						//SetTextAlign(hdc, TA_CENTER);
						//SelectObject(hdc, PrimaryListFont);
							//4/14/10
					DrawText(hdc, pSettings->status_string, _tcslen(pSettings->status_string), //ajige 5/18
						&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
						   //4/14/10
					rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;
					SelectObject(hdc, MainListFont);
					DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18 for wordwrap? need to reduce size of text
						&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
							//ExtTextOut(hdc, (rItem.right - rItem.left) / 2 + rItem.left,
							//rItem.bottom - rItem.top - SCALE(ITEM_FONT_SIZE) / 2 + rItem.top,
							//ETO_CLIPPED, &rClip, dItem.szPrimaryText, 
							//_tcslen(dItem.szPrimaryText), 0);
					rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;	
				}
				break;

				// allelimo: draw like phone, but no click (->listdata.cpp r176)
			case diDateTime:
					//slen = _tcslen(dItem.szPrimaryText);
					//4/15/10 needs to always paint in case of edit.
					//if (slen > 0) 
				{
					SelectObject(hdc, ItemDetailsFont);
					SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
						//SetTextAlign(hdc, TA_CENTER);
						//SetTextAlign(hdc, TA_RIGHT | TA_BOTTOM);
						//y = (rItem.bottom + rItem.top) / 2;

						// Draw the left label: "Start", "End", "Due", etc. -> szSecondaryText
						//rClip.right = rItem.left + padding * 5;
						//ajige 4/14/10: Due Date
					DrawText(hdc, dItem.szSecondaryText, _tcslen(dItem.szSecondaryText), //ajige 5/18
						&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
						//DrawText(hdc, pSettings->duedate_string, _tcslen(pSettings->duedate_string), //ajige 5/18
						//&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
						//ExtTextOut(hdc, rClip.right, 
						// y + SCALE(ITEM_DETAILS_FONT_SIZE) / 2,
						//ETO_CLIPPED, &rClip, dItem.szSecondaryText,
						//_tcslen(dItem.szSecondaryText), NULL);

						//rClip.left = rClip.right + 3;
						//rClip.right = rItem.right - padding;

						// Draw the right label: date for appointments -> szTertiaryText text 
						//rClip.right -= padding * 2;
					SelectObject(hdc, MainListFont);
					rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;					
					DrawText(hdc, dItem.szTertiaryText, _tcslen(dItem.szTertiaryText), //ajige 5/18 for wordwrap? need to reduce size of text
						&rClip2, DT_RIGHT |DT_WORDBREAK|DT_NOCLIP); //4/14/10
					
							//ExtTextOut(hdc, rItem.right - padding * 3, //allelimo: added *3
							//y + SCALE(ITEM_DETAILS_FONT_SIZE) / 2,
							//NULL, NULL, dItem.szTertiaryText, 
							// _tcslen(dItem.szTertiaryText), NULL);

						// Now display the hour (appointments) or the due date (tasks)
						//SetTextAlign(hdc, /*TA_CENTER*/TA_LEFT/*TA_RIGHT*/ | TA_BOTTOM);
						//SelectObject(hdc, PrimaryListFont);
						//SelectObject(hdc, SecondaryListFont);
					DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18 for wordwrap? need to reduce size of text
						&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); //4/14/10
			
							//ExtTextOut(hdc, rClip.left + padding * 3, //allelimo: changed to *3, was /3
							//y + SCALE(ITEM_FONT_SIZE) / 2,
							//ETO_CLIPPED, &rClip, dItem.szPrimaryText,
							//_tcslen(dItem.szPrimaryText), NULL);
					rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;	
			}
		break;

		case diOccurs:
			SelectObject(hdc, ItemDetailsFont);
			//slen = _tcslen(dItem.szPrimaryText);
			//if (slen > 0) 
			{
				SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
				
				DrawText(hdc, pSettings->occurs_string, _tcslen(pSettings->occurs_string), //ajige 5/18
					&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
				rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;
				SelectObject(hdc, MainListFont);
		   		DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18 for wordwrap? need to reduce size of text
						&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 	
				rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;	
			}
			break; 

		case diReminder:
			SelectObject(hdc, ItemDetailsFont);
			//slen = _tcslen(dItem.szPrimaryText);
			//if (slen > 0) 
			{
				SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
				
				DrawText(hdc, pSettings->reminder_string, _tcslen(pSettings->reminder_string), //ajige 5/18
					&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
				rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;
				SelectObject(hdc, MainListFont);
		   		DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18 for wordwrap? need to reduce size of text
						&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 	
				rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;	
			}
			break;
		
			// just like datetime, without secondary text and centerd
		case diCategory: ///4/5/10
				//SelectObject(hdc, SecondaryListFont);
			SelectObject(hdc, ItemDetailsFont);
            SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_DETAIL_MAIN_TEXT));
				//4/14/10
			DrawText(hdc, pSettings->categories_string, _tcslen(pSettings->categories_string), //ajige 5/18
				&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); //4/14/10
			rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;
			SelectObject(hdc, MainListFont);
			height=DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
				&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP|DT_CALCRECT); 
			if (height>MAINLIST_FONT_SIZE) //More than 1 line, needs to be placed further up
			{
				rClip2.top=rClip2.top-SCALE(DEFAULT_ITEM_HEIGHT)/6;//+SCALE(HEADER_HEIGHT)/2;
				DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
					&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP);
				rClip2.top=rClip2.top+SCALE(DEFAULT_ITEM_HEIGHT)/6;//+SCALE(HEADER_HEIGHT)/2;
			}
			else
				DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
					&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP);
			rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;	
				//ExtTextOut(hdc, rItem.left + padding, 
				//rItem.top + padding + 1,//ajige 5/18 added padding to have text further down, to make room for wordwrap
				//NULL, NULL, dItem.szPrimaryText,
				//_tcslen(dItem.szPrimaryText), NULL);
			break;

			

		case diSensitivity:
			SelectObject(hdc, ItemDetailsFont);
			//slen = _tcslen(dItem.szPrimaryText);
			//if (slen > 0) 
			{
				SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));				
				DrawText(hdc, pSettings->sensitivity_string, _tcslen(pSettings->sensitivity_string), //ajige 5/18
					&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
				rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;
				SelectObject(hdc, MainListFont);				
   				DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18 for wordwrap? need to reduce size of text
						&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
				rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;	
			}
			break;  

		case diAttendees:
			SelectObject(hdc, ItemDetailsFont);
			slen = _tcslen(dItem.szPrimaryText);
			//if (slen > 0) 
			{
				SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
				
				DrawText(hdc, pSettings->attendees_string, _tcslen(pSettings->attendees_string), //ajige 5/18
					&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP);
				rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;
					SelectObject(hdc, MainListFont);
   				DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18 for wordwrap? need to reduce size of text
						&rClip2, DT_RIGHT |DT_WORDBREAK|DT_NOCLIP);
				rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;	
			}
			break;
			
		case diNotes:
			SelectObject(hdc, ItemDetailsFont);
			//slen = _tcslen(dItem.szPrimaryText);
			//if (slen > 0) 
			{
				SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));				
				DrawText(hdc, pSettings->notes_string, _tcslen(pSettings->notes_string), //ajige 5/18
					&rClip, DT_LEFT |DT_WORDBREAK|DT_NOCLIP); 
				rClip2.left+=SCALE(DEFAULT_SCREEN_WIDTH)/3;
				SelectObject(hdc, MainListFont);
		   		height=DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
					&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP|DT_CALCRECT); 
				if (height>MAINLIST_FONT_SIZE) //More than 1 line, needs to be placed further up
				{
					rClip2.top=rClip2.top-SCALE(DEFAULT_ITEM_HEIGHT)/6;//+SCALE(HEADER_HEIGHT)/2;
					DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
						&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP);
					rClip2.top=rClip2.top+SCALE(DEFAULT_ITEM_HEIGHT)/6;//+SCALE(HEADER_HEIGHT)/2;
				}
				else
					DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18
						&rClip2, DT_LEFT |DT_WORDBREAK|DT_NOCLIP);
				rClip2.left-=SCALE(DEFAULT_SCREEN_WIDTH)/3;	
			}
			break;

        //case diDetailsButton:
					//SelectObject(hdc, PrimaryListFont);
				  //SetTextAlign(hdc, TA_CENTER);
					//DrawText(hdc, szTitle, -1, &rHeader, DT_CENTER | DT_VCENTER)
				   // ExtTextOut(hdc, (rHeader.right - rHeader.left) / 2 + rHeader.left,
						//(rHeader.bottom - rHeader.top - SCALE(ITEM_FONT_SIZE )) / 2 + rHeader.top,
					  // ETO_CLIPPED, &rClip, dItem.szPrimaryText, 
					   //     _tcslen(dItem.szPrimaryText), 0);
					//break;
        case diEditButton:
        //case diSaveContactButton:
			 // Display the button text
			SelectObject(hdc, PrimaryListFont);
			//SetTextAlign(hdc, TA_CENTER);
					DrawText(hdc, dItem.szPrimaryText, _tcslen(dItem.szPrimaryText), //ajige 5/18 for wordwrap? need to reduce size of text
							&rClip2, DT_CENTER |DT_WORDBREAK|DT_NOCLIP); //4/14/10
			
			//ExtTextOut(hdc, (rItem.right - rItem.left) / 2 + rItem.left,
			//	(rItem.bottom - rItem.top - SCALE(ITEM_FONT_SIZE) )/ 2 + rItem.top,  //ajige 1/22/10
						// rItem.bottom - rItem.top - SCALE(ITEM_FONT_SIZE) / 2 + rItem.top, bug introduced in v. 108
			//	ETO_CLIPPED, &rClip, dItem.szPrimaryText, 
			//	_tcslen(dItem.szPrimaryText), 0);

            break;
    }
}

/*5/5/10 not neccessary
void DrawExpandOn(HDC hdc, RECT rExpand, int yListOffset) //5/3/10
{
	int index=0;
	SelectObject(hdc, KeyboardFont);
	rExpand.bottom=rExpand.bottom*2;
	SelectObject(hdc, CreatePen(PS_SOLID, 1, GetSkinRGB(SKIN_COLOR_KEYBOARD_GRID)));
	DrawRect(hdc, &rExpand, GetSkinRGB(SKIN_COLOR_KEYBOARD_BACKGROUND));
	//SetBkMode(hdc, TRANSPARENT);
	
	
	int height = SCALE(DEFAULT_ITEM_HEIGHT);
	int indent = SCALE(LIST_ITEM_INDENT);
	HFONT hfOld = (HFONT)SelectObject(hdc, PrimaryListFont);
	rExpand.bottom = rExpand.top+ height;
	rExpand.left=rExpand.left+SCALE(ITEM_DETAILS_PADDING);
	
	SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_HIGHLIGHT));

	switch(dItem.type)
	{
		case diImportance:
			//if(nExpandedIndex>-1)//when nothing is chosen
			//		StartTransition(hWnd,ttContract,150);//,NULL);
				//nQueuedExpandedIndex =index;
				index=1;
				DrawText(hdc, pSettings->priority_string,-1,
					&rExpand, DT_CENTER | DT_TOP | DT_NOCLIP);				
			break;
		case diSensitivity:
			//if(nExpandedIndex>-1)//when nothing is chosen
			//		StartTransition(hWnd,ttContract,150);//,NULL);
				//nQueuedExpandedIndex =index;
				//ExpandIt(hWnd, 8);//nItem);	
			DrawText(hdc, pSettings->sensitivity_string,-1,
					&rExpand, DT_CENTER | DT_TOP | DT_NOCLIP);	
			index=8;
			break;
	}
	  
	SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
	
	nOptions = TaskEdits[index].filler(EditOptions, EditValuesT[index]);
	
	//for (int j = 0; j < nOptions; j++) 
		for (int j = 0; j < 20; j++) 
	{
		rExpand.left += indent;
		rExpand.top = rExpand.bottom;
		rExpand.bottom += height;
		Rectangle(hdc,rExpand.left-2,rExpand.top,rExpand.right,rExpand.bottom);//(hdc, &rExpand, GetSkinRGB(SKIN_COLOR_KEYBOARD_BACKGROUND));
		
		//DrawText(hdc, EditOptions[j],_tcslen(EditOptions[j]),
		//	&rExpand, DT_LEFT | DT_CENTER | DT_NOCLIP);
		DrawText(hdc, L"TEST",-1,
			&rExpand, DT_LEFT | DT_CENTER | DT_NOCLIP);
		//DrawRect(hdc, &rExpand, GetSkinRGB(SKIN_COLOR_KEYBOARD_BACKGROUND));
		//ExtTextOut(hdc, rItem.left + indent * 2, rItem.top + indent,
		//	ETO_CLIPPED, &rItemClip,
				//L"ExpansionTest", EditOptions[j],, NULL);
		rExpand.left -= indent;
		if (0 == _tcscmp(dItem.szPrimaryText, EditOptions[j])
			|| _tcslen(dItem.szPrimaryText) == 0
			&& _tcsstr(EditOptions[j], SZ_AUTO) == EditOptions[j]) 
		{					
				int radius = indent / 2;
				Ellipse(hdc, 
					rExpand.left-3 + indent/2 - radius,
					rExpand.top + height / 4 - radius,
					rExpand.left-3 + indent/2 + radius,
					rExpand.top + height / 4 + radius);
		}
	}
}*/

void DrawKeyboardOn(HDC hdc, RECT rKeyboard) {
	SelectObject(hdc, KeyboardFont);
	SelectObject(hdc, CreatePen(PS_SOLID, 1, GetSkinRGB(SKIN_COLOR_KEYBOARD_GRID)));
		//SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_KEYBOARD_TEXT));
	SetBkMode(hdc, TRANSPARENT);
		//int x, y, g, h;
	DATE dToday;
	TCHAR buffer[MAX_PATH];
	UnselectItem(); //5/3/10
	                
//4/27/10 test
//TODO finish up getting the color out
	SYSTEMTIME stOccur,st;
					//stOccur.wDay=GroupArray[cnt2].ID;
					stOccur.wMonth=stToday.wMonth;
					stOccur.wYear=stToday.wYear;

					DataItem * di;
					for (unsigned int j=0; j<vApptmnt.size(); j++)
					{
						di=vApptmnt.at(j);
						UINT g = di->iGroup;
						UINT uToday = _SystemToPoomInt();
						VariantTimeToSystemTime(g, &st);
						if(st.wMonth==stOccur.wMonth &&st.wYear==stOccur.wYear)
						{
							GroupArray[st.wDay].Color=0;
						}						
					}

//4/27/10
		//for (int i=0;i<49;i++) //ajige 5/19  the code below doesn't work right. Better to set at 0 right away.
			//ajige 5/18 either this or the corrected code below to set cells to 0
		//GroupArray[i].ID=0; //4/22/10 if this is done, the highlighting doesn't work 

	 const TCHAR * day[7] = {
		pSettings->sunday_string, pSettings->monday_string, pSettings->tuesday_string,
		pSettings->wednesday_string, pSettings->thursday_string, 
		pSettings->friday_string, pSettings->saturday_string
	}; 
	//allelimo: this is for first week day = monday
	 const TCHAR *  day2[7] = {
		pSettings->monday_string, pSettings->tuesday_string, pSettings->wednesday_string,
		pSettings->thursday_string, pSettings->friday_string, 
		pSettings->saturday_string, pSettings->sunday_string 
	}; 
		
	DrawRect(hdc, &rKeyboard, GetSkinRGB(SKIN_COLOR_KEYBOARD_BACKGROUND));

		 //SetTextAlign(hdc, TA_CENTER);

		// ajige  this code draws the month in the background of the calendar
		//SelectObject(hdc, KeyboardFont);
	SetBkMode(hdc, TRANSPARENT);
	SetTextColor(hdc, GetSkinRGB(/*SKIN_COLOR_KEYBOARD_GRID*/SKIN_COLOR_HIGHLIGHT));  //allelimo month text
		//KeyboardFont = BuildFont(20 * 100 / 80, TRUE, FALSE); 
		//GetLocalTime(&stToday);//ajige should come from date on agenda
	if(CompareString(LOCALE_NEUTRAL, NORM_IGNORECASE, pSettings->sort_tasks, -1, TEXT("Alphabetical"), -1) != CSTR_EQUAL
	   || History[depth].screen!=1)//ajige 6/1 from 2
	{					
		//TDALLELIMODATE
		GetDateFormat(LOCALE_USER_DEFAULT, 0, &stToday, TEXT("MMMM"), buffer, 20);
		DrawText(hdc, buffer,-1,
			&rKeyboard, DT_CENTER | /*DT_VCENTER DT_TOP*/DT_BOTTOM | DT_NOCLIP);	//allelimo month text

				//if (Keyboard_Ratio > 50)
					//			{
				//KeyboardFont = BuildFont(20 * 100 / 120, TRUE, FALSE);  //ajige from30/100
				//SelectObject(hdcMem, KeyboardFont);
				//SelectObject(hdcMem, KeyboardGridPen);
				//SetBkMode(hdcMem, TRANSPARENT);
				//SelectObject(hdcMem, KeyboardKeyBrush);
			//SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_KEYBOARD_TEXT));
		GroupWidth = 1 + ((rKeyboard.right - rKeyboard.left)-7) / 7 * 100 / 100;  //ajige from 6/5
		GroupHeight = 1 + ((rKeyboard.bottom - rKeyboard.top)-7) / 7 * 100 / 100;  //ajige from  7/6
		
		int cnt2 = 0;
	
		for(int h = 0; h < 7; h++)  //7 ajige from 6. 1 from 0 in order to draw dates starting in 2nd row
		{
			Rectangle(hdc, rKeyboard.left, rKeyboard.top + h * GroupHeight + h, rKeyboard.right, 
				rKeyboard.top + h * GroupHeight + h + 1);
			
			for(int g = 0; g < 7; g++)  //ajige from 5
			{
				if (h == 0)// in order to get vertical lines
				{
					Rectangle(hdc, rKeyboard.left + (g * GroupWidth) + g, rKeyboard.top, 
						rKeyboard.left + (g * GroupWidth) + g + 1, rKeyboard.bottom);
				}
								
				GroupArray[cnt2].Rect.left = rKeyboard.left + (g + 1) + (g * GroupWidth);
				GroupArray[cnt2].Rect.top = rKeyboard.top + (h + 1) + (h * GroupHeight);
				GroupArray[cnt2].Rect.right = GroupArray[cnt2].Rect.left + GroupWidth;
				GroupArray[cnt2].Rect.bottom = GroupArray[cnt2].Rect.top + GroupHeight;
					//stCurDay.wDay=GroupArray[CurrentGroup].ID
				SYSTEMTIME stNow;
				GetLocalTime(&stNow); //in order to get highlighted correct date

					//TODO when changing dates, highlight new date
				//4/22/10 if the id is set to 0 as in the beginning of the code, the 
				//GroupArray[cnt2].ID will always be 0, and then has to use the if ((cnt2-(f+7)) instead
				//However, this will cause some days not be highlighted, haven't figured out quite how yet.
				//TODO??
					//int f = stToday.wDayOfWeek - (stToday.wDay%7) + pSettings->doWeekStartSunday; //ajige To get what day the 1st of the month is on,starts on Sunday, 0 based
					//if ((cnt2-(f+7))== stToday.wDay //4/22/10 highlighting had stopped working, highlights the nth (day of month) square
				//4/26/10 TEST TODO: test for recurrences and then highlight
				//TODO not very efficient to go through the vector of items, for each date.
				//go through once:
				//restrict to displayed month
				//for ecah date with appointment, save the date to the GroupArray,
				//as separate item color.
					SYSTEMTIME stOccur,st;
					stOccur.wDay=GroupArray[cnt2].ID;
					stOccur.wMonth=stToday.wMonth;
					stOccur.wYear=stToday.wYear;

					DataItem * di;
					for (unsigned int j=0; j<vApptmnt.size(); j++)
					{
						di=vApptmnt.at(j);
						UINT g = di->iGroup;
						UINT uToday = _SystemToPoomInt();
						VariantTimeToSystemTime(g, &st);
						if(st.wDay==stOccur.wDay&&st.wMonth==stOccur.wMonth &&st.wYear==stOccur.wYear)
						{
							FillRect(hdc, &GroupArray[cnt2].Rect, CreateSolidBrush((COLORREF) GetSkinRGB(/*SKIN_COLOR_LIST_ITEM_MISSED*/SKIN_COLOR_HIGHLIGHT))); //allelimo "today"
								SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_HIGHLIGHT));
						}
						else
						{	
							SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_KEYBOARD_TEXT));//MessageBox(0,newItem,di->szTertiaryText,0);
						}
					}
				//4/26/10
				
				//4/27/10 highlight above the dates with appointments, use font color for today
				//TODO	doesn't work, seems to be either or ??????????
				//if (GroupArray[cnt2].ID== stToday.wDay
				//	&& stToday.wYear==stNow.wYear
				//	&& stToday.wMonth==stNow.wMonth
				//	&& stToday.wDay == stNow.wDay)
				//{
				//	FillRect(hdc, &GroupArray[cnt2].Rect, CreateSolidBrush((COLORREF) GetSkinRGB(SKIN_COLOR_HIGHLIGHT)));//SKIN_COLOR_HIGHLIGHT))); //allelimo "today" /*SKIN_COLOR_LIST_ITEM_MISSED)));
					//SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_MISSED));//SKIN_COLOR_HIGHLIGHT));
				//}
				//else
					//SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_KEYBOARD_TEXT));							
				cnt2++;
			}
							
				//ajige start
				//day captions ajige  3/25
				SelectObject(hdc, MainListFont);
				GroupArray[h].ID=0; //ajige 5/15 because of change in r85 -1;
				if (pSettings->doWeekStartSunday)
					DrawText(hdc,day[h],3,&GroupArray[h].Rect, DT_CENTER | DT_VCENTER | DT_NOCLIP);
				else	// week starts on monday
					DrawText(hdc,day2[h],3,&GroupArray[h].Rect, DT_CENTER | DT_VCENTER | DT_NOCLIP);
			}
						
				//WCHAR *newItem=LocalAlloc(LMEM_ZEROINIT,30);	
			TCHAR newItem[MAX_PATH] = {0};
			
				//TDALLELIMODATE
				//if (iMonthDay!=0)
				//	stToday.wMonth=stToday.wMonth+iMonthDay;
				//iMonthDay=0;
			stToday.wDay=stToday.wDay-1;
				//ajige 6/1 commented out below 2 lines because
				//it drew May dates and no month text
			SystemTimeToVariantTime(&stToday, &dToday);
			VariantTimeToSystemTime(dToday,&stToday);
		
			int f = stToday.wDayOfWeek - (stToday.wDay%7) + pSettings->doWeekStartSunday; //ajige To get what day the 1st of the month is on,starts on Sunday, 0 based
			
			//allelimo: this is for first week day = monday
			//need to add a setting too (later...)
			//int f=stToday.wDayOfWeek-(stToday.wDay%7);

			f=f+6;
			int maxdays[] =
			{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
			};
			
			if((stToday.wYear%4 == 0 && stToday.wYear % 100 != 0) || stToday.wYear%400 == 0) //leapyear
				maxdays[1]=29;
			//ajige the following draws the dates on the calendar
		
		for(int j=1;j<=maxdays[stToday.wMonth-1];j++)
		{
			wsprintf(newItem, TEXT("%i"), j);	
			if (j + f < 7)
				f = f + 7;	
			

			if(j < 10)  //ajige 3/25, otherwise may will start up in the title row
			{
				DrawText(hdc, newItem, 1, &GroupArray[j+f].Rect, DT_CENTER | DT_VCENTER | DT_NOCLIP);
			}
			else
				DrawText(hdc, newItem, 2, &GroupArray[j+f].Rect, DT_CENTER | DT_VCENTER | DT_NOCLIP);
			GroupArray[j+f].ID = j; //in order to save the day for when it's clicked
			
		}
		
		//ajige 5/18 to set all cells to 0 that doesn;t have a date in it
		//ajige 5/19 still wasn't working right. Set to 0 at beginning.
				/*for (int j=48;j>maxdays[stToday.wMonth-1]+1;j--)
					GroupArray[j].ID=0;
				if (f > 7)
					for(int j = 7; j < f; j++)
							GroupArray[j].ID =0; //ajige 5/15 because of change in r85 -1;
			*/
			//TDALLELIMODATE
			//KeyboardFont = BuildFont(40 * 100 / 90, TRUE, FALSE);  //ajige from30/100
		Rectangle(hdc, rKeyboard.right - 1, rKeyboard.top, rKeyboard.right, rKeyboard.bottom);
		Rectangle(hdc, rKeyboard.left, rKeyboard.bottom - 1, rKeyboard.right, rKeyboard.bottom);						
		stToday.wDay = stToday.wDay + 1;
	}
	else
	{
			//ajige commented out: should there be 2 keyboards, one to select items based on title, one based on date???
			//ajige 5/26 added back for when tasks are sorted alphabetical
			// Draw the horizontal lines
		GroupWidth = 1 + ((rKeyboard.right - rKeyboard.left)-6) / 5 * 100 / 100-1;  //ajige from 6/5
			//GroupWidth =(rKeyboard.right - rKeyboard.left) / 5; 
		GroupHeight = 1 + ((rKeyboard.bottom - rKeyboard.top)-7) / 6 * 100 / 100;  //ajige from  7/6
		for (int h = 0; h < nKeyboardRows; h++) {
			int y = rKeyboard.top + h 
				* (rKeyboard.bottom - rKeyboard.top) / nKeyboardRows;
			MoveToEx(hdc, rKeyboard.left, y, (LPPOINT) NULL);
			LineTo(hdc, rKeyboard.right, y);
		}
		MoveToEx(hdc, rKeyboard.left, rKeyboard.bottom - 1, (LPPOINT) NULL);
		LineTo(hdc, rKeyboard.right, rKeyboard.bottom - 1);

		// Draw the vertical lines
		for (int g = 0; g < nKeyboardCols; g++) {
			int x = rKeyboard.left + g 
				* (rKeyboard.right - rKeyboard.left) / nKeyboardCols;
			MoveToEx(hdc, x, rKeyboard.top, (LPPOINT) NULL);
			LineTo(hdc, x, rKeyboard.bottom);
		}
		MoveToEx(hdc, rKeyboard.right - 1, rKeyboard.top, (LPPOINT) NULL);
		LineTo(hdc, rKeyboard.right - 1, rKeyboard.bottom);

		// Draw the letters
		int i = 0;
		for (int h = 0; h <= nKeyboardRows; h++) {
			int y = rKeyboard.top 
				+ (GroupHeight - SCALE(KEYBOARD_FONT_SIZE) / 2) 
				+ (GroupHeight * h);
			for (int g = 0; g < nKeyboardCols; g++) {
			   int x = rKeyboard.left + (GroupWidth / 2) + (GroupWidth * g);
				 if (i < nKeyboardLetters) {
					ExtTextOut(hdc, x, y, NULL, NULL, &alphabet[i++], 1, 0);
				}
			}
		}
	}
}

void DrawHeaderOn(HDC hdc, RECT rHeader, HDC hdcSkin) {
	int nIconWidth = SCALE(MENU_BAR_ICON_WIDTH);
	int nHeaderHeight = SCALE(SKIN_HEADER_HEIGHT);
	int nYOffset = SCALE(SKIN_HEADER_Y_OFFSET);

    // The background of the header bar
    StretchBlt(hdc, rHeader.left, rHeader.top, 
        rHeader.right - rHeader.left, rHeader.bottom - rHeader.top,
		hdcSkin, 0, nYOffset, 1,
		nHeaderHeight, SRCCOPY);

    if (!bTransitioning) {
        // The "back" button
        //if (Screens[History[depth].screen].parent >= 0) {
		if(Screens[History[depth].screen].hgScreen>=2)
		{			
			StretchBlt(hdc, 
				rHeader.left, rHeader.top, 
				nIconWidth, nHeaderHeight,
				hdcSkin, 
				0, nYOffset, 
				nIconWidth,	nHeaderHeight,
				SRCCOPY);

			if(Screens[History[depth].screen].parent==3)
			{//ajige forward button on agenda screen
				StretchBlt(hdc, 
					rHeader.right - nIconWidth, rHeader.top,
					nIconWidth, nHeaderHeight,
					hdcSkin, 
					nIconWidth, nYOffset, 
					nIconWidth, nHeaderHeight,
					SRCCOPY);
			}
        
		}
        // The "+" to add a contact
        if (Screens[History[depth].screen].fnAdd != NULL) {
			StretchBlt(hdc, 
				rHeader.right - nIconWidth, rHeader.top,
				nIconWidth, nHeaderHeight,
				hdcSkin, 
				nIconWidth * 4, nYOffset, 
				nIconWidth, nHeaderHeight,
				SRCCOPY);
        }
     
    }

    // The title
    SelectObject(hdc, PrimaryListFont);
    SetBkMode(hdc, TRANSPARENT);
    SetTextAlign(hdc, TA_LEFT);

    SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_HEADER_TEXT));

    TCHAR szTitle[PRIMARY_TEXT_LENGTH] = {0};
	TCHAR bDate[20]={0};   //ajige
	GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stToday,
		NULL, bDate, 20);//ajige
			 
    HRESULT hr = Screens[History[depth].screen].fnGetTitle(Screens[History[depth].screen],//ajige
        &History[depth-1].data, szTitle, PRIMARY_TEXT_LENGTH, pSettings);
	if(History[depth].screen==2)//.hgScreen==2)
	{
		StringCchCat(szTitle, PRIMARY_TEXT_LENGTH, TEXT(": "));  //ajige
		StringCchCat(szTitle, PRIMARY_TEXT_LENGTH, bDate);  //ajige
	}
    DrawText(hdc, szTitle, -1, &rHeader, DT_CENTER | DT_VCENTER); 
}

// TODO: this more efficiently
void DrawCanvasOn(HDC hdc, RECT rect) {
	int canvasHeight = SCALE(SKIN_CANVAS_HEIGHT);
    for (int i = rect.top; i < rect.bottom; i += canvasHeight) {
		int h = i + canvasHeight > rect.bottom ? rect.bottom - i : canvasHeight;
        BitBlt(hdc, rect.left, i, rect.right - rect.left, 
            canvasHeight, hdcCanvas, 0, 0, SRCCOPY);
    }
}

//-----------------------------------------------------------------------------
// Utility functions
//

void InitSurface(HWND hWnd) {
    HRESULT hr = S_OK;
	HDC hdc;
	hdc = GetDC(hWnd);

    // Update the RECTs for the individual sections
	GetClientRect(hWnd, &rScreen);
    nScreenHeight = rScreen.bottom - rScreen.top;
    int nScreenWidth = rScreen.right - rScreen.left;

    // Title bar, with date, carrier, battery, signal strength, etc.
	rTitlebar = rScreen;
	if (pSettings->doShowFullScreen) {
		rTitlebar.bottom = rTitlebar.top + SCALE(TITLE_BAR_HEIGHT);

		// Location of the name of the service
		rServiceTitle = rTitlebar;
		rServiceTitle.bottom *= 2;
		rServiceTitle.left += SCALE(SIGNAL_WIDTH);
		rServiceTitle.right = rServiceTitle.right / 2 - SCALE(SIGNAL_WIDTH);
	}
	else {
		// collapse new titlebar so it is not active
		rTitlebar.bottom = rTitlebar.top;
		rServiceTitle = rTitlebar;
	}

    // Header, with the "back" button, the "favorite" button, etc.
    rHeader = rScreen;
    rHeader.top = rTitlebar.bottom;
	rHeader.bottom = rHeader.top + SCALE(HEADER_HEIGHT);

    // Menu at the bottom of the screen
	rMenubar = rScreen;
	rMenubar.top = rMenubar.bottom - SCALE(MENU_BAR_HEIGHT);

    // From the header to the bottom of the screen
    rContent = rScreen;
    rContent.top = rHeader.bottom;

    // Between the header and the menu bar
	rList = rContent;
	rList.bottom = rMenubar.top;
    rListHeight = rList.bottom - rList.top;

    // Calculate how many rows / cols for the keyboard
    double screenRatio = (double)nScreenWidth / nScreenHeight;
    nKeyboardRows = 1;
    nKeyboardCols = 1;
    while (nKeyboardRows * nKeyboardCols < nKeyboardLetters) {
        if (nScreenWidth < nScreenHeight) {
            nKeyboardRows = (int)(++nKeyboardCols / screenRatio);
        }
        else {
            nKeyboardCols = (int)(++nKeyboardRows * screenRatio);
        }
    }
    if (nScreenWidth < nScreenHeight) {
        while ((nKeyboardRows - 1) * nKeyboardCols >= nKeyboardLetters) {
            nKeyboardRows--;
        }
    }
    else {
        while (nKeyboardRows * (nKeyboardCols - 1) >= nKeyboardLetters) {
            nKeyboardCols--;
        }
    }
    GroupWidth = nScreenWidth / nKeyboardCols;
    GroupHeight = nScreenHeight / nKeyboardRows;


    // Initialize the DCs and Bitmaps
    if (hdcMem)
        CBR(DeleteDC(hdcMem));
    hdcMem = CreateCompatibleDC(hdc);
    if (hbmMem)
        CBR(DeleteObject(hbmMem));
	hbmMem = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
    SelectObject(hdcMem, hbmMem);

    if (hdcTmp)
        CBR(DeleteDC(hdcTmp));
    hdcTmp = CreateCompatibleDC(hdc);
	if (hbmTmp)
        CBR(DeleteObject(hbmTmp));
	hbmTmp = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
    SelectObject(hdcTmp, hbmTmp);

    if (hdcPage1)
        CBR(DeleteDC(hdcPage1));
    hdcPage1 = CreateCompatibleDC(hdc);
    if (hbmPage1)
        CBR(DeleteObject(hbmPage1));
    hbmPage1 = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
    SelectObject(hdcPage1, hbmPage1);

    if (hdcPage2)
        CBR(DeleteDC(hdcPage2));
    hdcPage2 = CreateCompatibleDC(hdc);
    if (hbmPage2)
        CBR(DeleteObject(hbmPage2));
    hbmPage2 = CreateCompatibleBitmap(hdc, nScreenWidth, nScreenHeight);
    SelectObject(hdcPage2, hbmPage2);

    // Initialize skin
    if (!hbmSkin) {
		InitializeSkin(hdc);
	}

	InitializeCanvas();

    CBR(ReleaseDC(hWnd, hdc));

Error:
    ASSERT(SUCCEEDED(hr));
}

COLORREF GetSkinRGB(int index) {
	COLORREF c = GetPixel(hdcSkin, SCALE(index), 
		SCALE(SKIN_COLORS_Y_OFFSET));
	return c;
}

void InitializeSkin(HDC hdc) {
    HBITMAP hbmSkinFile = SHLoadImageFile(pSettings->skin_path);
	int nScreenWidth = SCALE(DEFAULT_SCREEN_WIDTH);
	int nSkinHeight = SCALE(DEFAULT_SKIN_HEIGHT);

	BITMAP bmp;
	GetObject(hbmSkinFile, sizeof(bmp), &bmp);

    // Load skin
	HGDIOBJ hTmpOld = SelectObject(hdcTmp, hbmSkinFile);

	// Create skin bitmap
	hbmSkin = CreateCompatibleBitmap(hdc, nScreenWidth, nSkinHeight);

	hdcSkin = CreateCompatibleDC(hdc);
	SelectObject(hdcSkin, hbmSkin);

	// Stretch skin to properly fit the screen
	StretchBlt(hdcSkin, 0, 0, nScreenWidth, nSkinHeight,
		hdcTmp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);

	// Restore the original hdcTmp bitmap
	SelectObject(hdcTmp, hTmpOld);
}

void InitializeCanvas() {

	int nScreenWidth = ::GetSystemMetrics(SM_CXSCREEN);
	int nItemHeight = SCALE(DEFAULT_ITEM_HEIGHT);
	
    if (hdcCanvas)
        DeleteDC(hdcCanvas);
    
	hdcCanvas = CreateCompatibleDC(hdcSkin);
    
	if (hbmCanvas)
        DeleteObject(hbmCanvas);
    
	hbmCanvas = CreateCompatibleBitmap(hdcSkin,
		nScreenWidth, nItemHeight);

    SelectObject(hdcCanvas, hbmCanvas);

	int textureWidth = SCALE(DEFAULT_SCREEN_WIDTH);
	int textureHeight = SCALE(SKIN_CANVAS_HEIGHT);

    BitBlt(hdcCanvas, 0, 0, textureWidth, textureHeight,
		hdcSkin, 0, SCALE(SKIN_CANVAS_Y_OFFSET), SRCCOPY);

    // copy the texture to the full screen width (if in landscape mode)
    if (textureWidth < nScreenWidth) {
        BitBlt(hdcCanvas, textureWidth, 0, 
            nScreenWidth - textureWidth, textureHeight,
            hdcCanvas, 0, 0, SRCCOPY);
    }

    // copy the texture to the full DEFAULT_ITEM_HEIGHT * vga
	// several BitBlt's is faster than one StretchBlt
	for (int i = textureHeight; i < nItemHeight; i += i) {
		int h = i + i > nItemHeight 
			? nItemHeight - i 
			: i;
        BitBlt(hdcCanvas, 0, i, nScreenWidth, h, hdcCanvas, 0, 0, SRCCOPY);
    }
}

void CalculateHeights() {
	int c = 0;

    TCHAR letter[2];
    TCHAR * pdest;
    int index;
    DataItem dItem;

    letter[1] = 0;
    int count = GetItemCount();

    nKeyboardLetters = _tcslen(pSettings->alphabet);
    bool bAutoAlphabet = nKeyboardLetters == 0;

	

    StringCchCopy(alphabet, ALPHABET_MAX_SIZE, pSettings->alphabet);

    for (int i = 0; i < ALPHABET_MAX_SIZE; i++) {
        GroupPosition[i] = -1;
    }

    if (count == 0) {
        ListHeight = maxScrolled = 0;
		AverageItemHeight = SCALE(DEFAULT_ITEM_HEIGHT);
        return;
    }

	vStartPosition.clear();
    for (int i = 0; i < count; i++) {
		vStartPosition.push_back(c);

		int h = SCALE(DEFAULT_ITEM_HEIGHT);

        dItem = GetItem(i);
        if (NULL != Screens[History[depth].screen].fnGetGroup
            && IsItemNewGroup(i) && dItem.iGroup) {

				h += SCALE(DEFAULT_GROUP_HEIGHT);

            Screens[History[depth].screen].fnGetGroup(Screens[History[depth].screen], //ajige
				&dItem, letter, 2, pSettings);

            pdest = _tcsstr(pSettings->alphabet, letter);
            index = (int)(pdest - pSettings->alphabet);
            if (index >= 0 && index < ALPHABET_MAX_SIZE) {
                GroupPosition[index] = c;
            }
            else if (bAutoAlphabet && nKeyboardLetters < ALPHABET_MAX_SIZE) {
                GroupPosition[nKeyboardLetters] = c;
                alphabet[nKeyboardLetters] = letter[0];
                nKeyboardLetters++;
            }
        }

        c += h;
    }

	vStartPosition.push_back(c);

    if (GroupPosition[0] == -1)
        GroupPosition[0] = 0;

    for (int i = 1; i < ALPHABET_MAX_SIZE; i++) {
        if (GroupPosition[i] == -1)
            GroupPosition[i] = GroupPosition[i-1];
    }

	ListHeight = c;
    int cListHeight = Screens[History[depth].screen].hasMenus
       ? rListHeight : rContent.bottom - rContent.top;   

	 maxScrolled = ListHeight > cListHeight ? ListHeight - cListHeight : 0;
    AverageItemHeight = ListHeight / count;

	/*if (nExpandedIndex >= 0) 
	{ //TODO: doesn't make the expanded stay on the screen when scrolled
        int tmp = rExpandedHeight;
        if (bTransitioning) 
            tmp = (int)(tmp * dTransitionPct);
        ListHeight += tmp;		
    }*/
	
}

int GetItemHeight(int index) {
	ASSERT(index < (int)vStartPosition.size());
	return vStartPosition[index+1] - vStartPosition[index];
}

int GetStartPosition(int index) {
	ASSERT(index < (int)vStartPosition.size());

	return vStartPosition[index];
}

int GetPixelToItem(int y) {
	ASSERT(vStartPosition.size() > 0);

	y = min(ListHeight - 1, y);
	y = max(0, y);

	// estimate based on DEFAULT_ITEM_HEIGHT * vga
	int guess = y / AverageItemHeight;
	int max = GetItemCount();
	if (guess > max)
		guess = max;

	while (y < vStartPosition[guess] && guess > 0) {guess--;}

	while (y >= vStartPosition[guess+1] && guess < max) {guess++;}

	return guess;
}

// todo: check this function
void ScrollBar(int y) {
	bScrolling = true;
	Velocity = 20;

    // if "Agenda", scroll by chunks of A,B,C,etc.
    if (nCurrentTab == 2) {
        int index = (y - rList.top) * nKeyboardLetters / rListHeight;
        History[depth].scrolled = index < 0 ? 0
            : index >= nKeyboardLetters ? maxScrolled
            : GroupPosition[index];
    }

    // otherwise, just do a normal scroll
    else {
        double pct = (double)(y - rList.top) 
            / (double)rListHeight;
	    History[depth].scrolled = (int)(maxScrolled * pct);
    }

    History[depth].scrolled = min(History[depth].scrolled, maxScrolled);
    History[depth].scrolled = max(History[depth].scrolled, 0);
}

void ScrollTo(HWND hWnd, int position, int duration) {
    if (position < minScrolled)
        position = minScrolled;
    if (position > maxScrolled)
        position = maxScrolled;

    Scroll_StartPosition = History[depth].scrolled;
	Scroll_Change = position - Scroll_StartPosition;
	Scroll_Duration = duration;
	Scroll_StartTime = ::GetTickCount();
	Scroll_TimeCounter = 0;
	SetTimer(hWnd, IDT_TIMER_SCROLL_TO, REFRESH_RATE, NULL);

}

void StartTransition(HWND hWnd, TransitionType tr, int duration)//, DataItem dItem)
{
    if (duration == 0)
        return;
//MessageBox(0,L"StartTransition",L"",0);
    bTransitioning = true;
    nTransitionDuration = duration;
    dTransitionPct = 0.0;
    trTransitionType = tr;

    // Save a snapshot of the current screen
    BitBlt(hdcPage1, rScreen.left, rScreen.top, 
        rScreen.right - rScreen.left, 
        rScreen.bottom - rScreen.top, 
        hdcMem, rScreen.left, rScreen.top, SRCCOPY);
//MessageBox(0,L"StartTransition2",L"",0);

    if (tr == ttSlideLeft || tr == ttSlideRight) {
        DrawScreenOn(hdcPage2, rScreen, hdcTmp, History[depth].scrolled);
    }
    else if (tr == ttKeyboardExpand || tr == ttKeyboardShrink) {
		//MessageBox(0,L"ttKeyboardExpand",L"StartTransition",0);
        DrawKeyboardOn(hdcPage2, rScreen);
    }

	//else if (tr == ttEditExpand || tr == ttEditShrink) {
   //     DrawExpandOn(hdcPage2, rScreen,History[depth].scrolled);
    //}
	//else  //4/21/10 not neccessary
		//DrawExpanded(hdcPage2,rScreen);
	//MessageBox(0,L"StartTransition3",L"",0);

	dwTransitionStart = ::GetTickCount();

    InvalidateRect(hWnd, &rScreen, FALSE);
//MessageBox(0,L"StartTransition4",L"",0);

	SetTimer(hWnd, IDT_TIMER_TRANSITION, REFRESH_RATE, NULL);
}

bool ParseCommandLine(HWND hWnd, LPTSTR lpCmdLine) {
    const struct CmdLineArg cmdLineArgs[] = {
        TEXT("-appointments"), CMD_GOTO_APPS,
        TEXT("-tasks"), CMD_GOTO_TASKS,
        TEXT("-agenda"), CMD_GOTO_AGENDA,
			//TEXT("-dialer"), CMD_GOTO_SETTINGS,
        TEXT("-calendar"), CMD_GOTO_CALENDAR,
			//TEXT("-details"), CMD_GOTO_DETAILS,

			// -add has to be below -contacts in this struct
			//TEXT("-add"), CMD_ADD,

    };

	if (_tcslen(lpCmdLine) == 0)
		return false;

	bool handled = false;
	TCHAR * cmdParam;

	for (int i = 0; i < ARRAYSIZE(cmdLineArgs); i++) {
		cmdParam = _tcsstr(lpCmdLine, cmdLineArgs[i].arg);
		if (cmdParam != NULL) {
			// search after the parameter for a number
			LPARAM lParam = _ttol(cmdParam + _tcslen(cmdLineArgs[i].arg));

			PostMessage(hWnd, WM_COMMAND, cmdLineArgs[i].wparam, lParam);
			handled = true;
		}
	}

	return handled;
}

void CalculateClickRegion(POINT p) {
    // They clicked on the popup, no matter what screen
    if (bDisplayingPopup) 
	{
    }

    // They clicked in the bottom menus
    else if (Screens[History[depth].screen].hasMenus 
        && PtInRect(&rMenubar, p)) {
        rClickRegion = rMenubar;
    }
	//ajige 4/24 combined all clicking in header bar to one else if:
	else if(p.y>=rHeader.top && p.y < rHeader.bottom)//ajige 5/13 from: .top+HEADER_CLICK_HEIGHT * vga)
	{
    // highlight "back" button in header bar , only for agenda and details
		if (depth > 0 
        && p.x <= SCALE(HEADER_CLICK_HEIGHT)
		&& (Screens[History[depth].screen].parent == 0 //ajige 4/23
		||History[depth].screen==2)){
				//|| Screens[History[depth].screen].hgScreen==2)){  
				//&& Screens[History[depth].screen].parent >= 0) {
			rClickRegion.top = rHeader.top;
#ifndef AJIGE_PRIVATE_BUILD
			rClickRegion.bottom = rHeader.top + SCALE(HEADER_CLICK_HEIGHT);
#else
			rClickRegion.bottom = rHeader.bottom;//ajige changed because otherwise it highlights more than the row. Original: rHeader.top + HEADER_CLICK_HEIGHT * vga;
#endif
			rClickRegion.left = 0;
			rClickRegion.right = SCALE(HEADER_CLICK_HEIGHT);
		}

		// "+" button in header bar tasks or apptmt   or
		//forward in the agenda screen
		else if (
			(Screens[History[depth].screen].fnAdd != NULL  //AJIGE 4/23
				//|| Screens[History[depth].screen].fnToggleFavorite != NULL
				//(Screens[History[depth].screen].hgScreen==0
				//||Screens[History[depth].screen].hgScreen==1
			||History[depth].screen==2)
			&& p.x >= rList.right - SCALE(HEADER_CLICK_HEIGHT)) {

			rClickRegion.top = rHeader.top;
#ifndef AJIGE_PRIVATE_BUILD
			rClickRegion.bottom = rHeader.top + SCALE(HEADER_CLICK_HEIGHT);
#else
			rClickRegion.bottom = rHeader.bottom; //ajige: see Above  rHeader.top + HEADER_CLICK_HEIGHT * vga;
#endif
			rClickRegion.left = rList.right - SCALE(HEADER_CLICK_HEIGHT);
			rClickRegion.right = rList.right;
		}
		else if(History[depth].screen==2)//ajige 4/24 highlight middle click
		{
			rClickRegion.top = rHeader.top;
#ifndef AJIGE_PRIVATE_BUILD
			rClickRegion.bottom = rHeader.top + SCALE(HEADER_CLICK_HEIGHT);
#else
			rClickRegion.bottom = rHeader.bottom; //ajige: see Above  rHeader.top + HEADER_CLICK_HEIGHT * vga;
#endif
			rClickRegion.left = SCALE(HEADER_CLICK_HEIGHT);
			rClickRegion.right = rList.right - SCALE(HEADER_CLICK_HEIGHT);
		}
		else 
			goto NONCLICKABLE;
	}
    // They clicked the service title
    else if (PtInRect(&rServiceTitle, p)) //&& hasiDialerServices) //5/5/10 not neccessary??
	{
        rClickRegion = rServiceTitle;
	}

    // They clicked in the titlebar
    // no matter what the screen type is
	else if (PtInRect(&rTitlebar, p)) {
        rClickRegion = rTitlebar;
	}

    // Clicked a list item
    else if (p.y >= rList.top) {
        int offsety = History[depth].scrolled - rList.top;
        int listy = p.y + offsety;

		if (GetItemCount() == 0)
			goto NONCLICKABLE;

        int nItem = GetPixelToItem(listy);
        if (!CanSelectItem(nItem))
            goto NONCLICKABLE;

		rClickRegion.top = GetStartPosition(nItem) - offsety;
		rClickRegion.bottom = rClickRegion.top + GetItemHeight(nItem);

		rClickRegion.top = max(rClickRegion.top, rList.top);

        if (Screens[History[depth].screen].hasMenus)
            rClickRegion.bottom = min(rClickRegion.bottom, rMenubar.top);
        rClickRegion.left = rList.left;
        rClickRegion.right = rList.right;

        if (p.y < rClickRegion.top || p.y > rClickRegion.bottom)
            goto NONCLICKABLE;
    }

    // Clicked on a non-clickable region
    else {
        goto NONCLICKABLE;
    }

    return;

NONCLICKABLE:
    rClickRegion.top = -1;
    rClickRegion.bottom = -1;
}

void GetIDialerServiceName() {
    TCHAR value[128] = {0};
    TCHAR key[32] = {0};

	LoadSetting(value, 128, IDIALER_REG_KEY, SERVICE_NUM, NULL);

    if (value[0] == 0) {
        // no iDialer setting found
        szWindowTitle[0] = 0;
        return;
    }

    int nService = _wtoi(value);

    StringCchPrintf(key, 32, SERVICE_TITLE_FORMAT, nService + 1);
	LoadSetting(value, 64, IDIALER_REG_KEY, key);
    StringCchCopy(szWindowTitle, 64, value);
}

void NextIDialerService() {
    TCHAR value[128] = {0};
    TCHAR key[32] = {0};

	LoadSetting(value, 128, IDIALER_REG_KEY, SERVICE_NUM, NULL);

    if (value[0] == 0) {
        // no iDialer setting found
        szWindowTitle[0] = 0;
        return;
    }

    // +1 because we want the next one
    int nService = _wtoi(value) + 1;

    StringCchPrintf(key, 32, SERVICE_TYPE_FORMAT, nService + 1);
	LoadSetting(value, 64, IDIALER_REG_KEY, key);

    // the next service doesn't exist, so drop down to 1
    if (value[0] == 0)
        nService = 0;

    StringCchPrintf(value, 128, TEXT("%d"), nService);
	SaveSetting(IDIALER_REG_KEY, value, SERVICE_NUM);
}

bool HasMultipleIDialerServices() { //remove??
    TCHAR value[128] = {0};
    TCHAR key[32] = {0};

    // If "service2type" exists, then we know they have > 1 iDialer services
    StringCchPrintf(key, 32, SERVICE_TYPE_FORMAT, 2);
	LoadSetting(value, 128, IDIALER_REG_KEY, key, NULL);

    return value[0] != 0;
}

//based on code from: http://www.codeproject.com/KB/mobile/dt_end_ellipsis.aspx
LPTSTR WriteEllipsis(HDC hdc, LPTSTR szIn, RECT rect)
{
	int	nCount;
	SIZE   szStr;
	LPTSTR lpStr;  
	int    nWidth; 

	
	lpStr  = (LPTSTR)szIn;							// Make it non-const             
	nWidth = rect.right - rect.left - SCALE(65);//ajige 3/25 from 50	// Rect width
	nCount = _tcslen(lpStr);						// String lenght

	// Check if the text extent is larger than the rect's width
	GetTextExtentPoint32(hdc, lpStr, nCount, &szStr);
	if(szStr.cx > nWidth)
	{
		int nEstimate = (nCount * nWidth) / szStr.cx + 1;

		if(nEstimate < nCount)
			nCount = nEstimate;

		// Insert the initial ellipsis, by replacing the last char
		lpStr[nCount-1] = ELLIPSIS;
		GetTextExtentPoint32(hdc, lpStr, nCount, &szStr);

		// While the extents are larger than the width, remove one
		// character at the time
		while(szStr.cx > nWidth && nCount > 1)
		{
			lpStr[--nCount] = 0;        // Remove last

			lpStr[nCount-1] = ELLIPSIS; // Replace last with ...


			GetTextExtentPoint32(hdc, lpStr, nCount, &szStr);
		}
	}

	return lpStr;
}

//bool 4/1/10
/*VARIANT_BOOL TaskIsComplete(int nIndex) //ajige 2/12  doesn't work for drawing
{
	HRESULT hr;
	IFolder * pCurrFldr = NULL;
	IPOutlookItemCollection * pItemCol = NULL;
	IPOutlookApp2 *             polApp;
	HWND hWnd = 0;
	ITask *pTask = NULL;
	VARIANT_BOOL vbIsComplete;

	 if (polApp == NULL) {
        hr=CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
                              __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
        CHR(hr);
    
		hWnd = FindWindow (SZ_APP_NAME, NULL);
		hr= polApp->Logon((long)hWnd);
		CHR(hr);		
    }

    //hr = S_OK;


	hr= polApp->GetDefaultFolder(olFolderTasks, &pCurrFldr);
	CHR(hr);		
		//GetPoomFolder(olFolderTasks,&pFolder);
	hr= pCurrFldr->get_Items(&pItemCol);
	CHR(hr);
	hr= pItemCol->Item(++nIndex, reinterpret_cast<IDispatch**>(&pTask));
	CHR(hr);
	hr= pTask->get_Complete(&vbIsComplete);
	CHR(hr);

Error:
		//RELEASE_OBJ(pCurrFldr);
		if (FAILED(hr)) {
			 //If we failed to log on, don't keep the object around
			RELEASE_OBJ(polApp);
		}
	return vbIsComplete;
}
*/
//4/16/10 for edit screen

// generic setting handlers

void UpdateItem(int iLine,DataItem dItem)//5/3/10
{
	extern IPOutlookApp2 *             polApp;
	 HRESULT    hr;
	 ITask * pTask = NULL;
	if (polApp == NULL) 
	{
		hr = CoCreateInstance(__uuidof(Application), NULL, CLSCTX_INPROC_SERVER,
						  __uuidof(IPOutlookApp2), (LPVOID*) &polApp);
		CHR(hr);

		HWND hWnd = FindWindow (SZ_APP_NAME, NULL);
		hr = polApp->Logon((long)hWnd);
		CHR(hr);
	}

	hr = S_OK;

	Error:
		//RELEASE_OBJ(pItem);//ajige moved 
		//RELEASE_OBJ(pFolder);//ajige moved 
	if (FAILED(hr)) {
		// If we failed to log on, don't keep the object around
		RELEASE_OBJ(polApp);
	}
	int oid = dItem.oId;
	if (oid == -1)
	return ;//E_INVALIDARG;

	hr = polApp->GetItemFromOid((CEOID)dItem.oId, (IDispatch**)&pTask);
	CHR(hr);
	switch(dItem.type)
	{
		case diImportance:
			hr=pTask->put_Importance(iLine);
			break;
		case diSensitivity:
			hr=pTask->put_Sensitivity(iLine);
			break;
		case diStatus:
			hr=pTask->put_Complete(iLine);
			break;
		case diReminder:
			hr=pTask->put_ReminderSet(iLine);
			break;
		case diOccurs:
			//not put recurrence
			break;
		
	}

		//if (dItem.type==diImportance)
		//	hr=pTask->put_Importance(iLine);//put_Complete(VARIANT_FALSE); 
		//else if (dItem.type==diSensitivity)
		//	hr=pTask->put_Sensitivity(iLine);
	hr=pTask->Save();
	CHR(hr);
	isPoomTainted=true;
		//end 4/21/10
		//InvalidateRect(hWnd, &rContent, false);
}
/*5/5/10 not neccessary
void DrawOnOff(HDC hdc, RECT rect, bool value) {
    SetTextAlign(hdc, TA_RIGHT | TA_BOTTOM);
    SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));

    int baseline = rect.bottom 
		- SCALE(DEFAULT_ITEM_HEIGHT - ITEM_SECONDARY_FONT_SIZE) / 2;

    const TCHAR * szOnOff = value ? SZ_ON : SZ_OFF;

    HFONT hfOld = (HFONT)SelectObject(hdc, SecondaryListFont);

	ExtTextOut(hdc, rect.right - SCALE(LIST_ITEM_INDENT), baseline,
		ETO_CLIPPED, &rect, szOnOff, _tcslen(szOnOff), NULL);

    SelectObject(hdc, hfOld);
}*/
/*5/5/10 not neccessary
void DrawValue(HDC hdc, RECT rect, const TCHAR * value) {
		//HFONT hfOld = (HFONT)SelectObject(hdc, PrimaryListFont); //big
	HFONT hfOld = (HFONT)SelectObject(hdc, MainListFont);//bold
		//HFONT hfOld = (HFONT)SelectObject(hdc, ItemDetailsFont);//tiny
		//HFONT hfOld = (HFONT)SelectObject(hdc, ListIndicatorFont);//huge
		//HFONT hfOld = (HFONT)SelectObject(hdc, SecondaryListFont);//bold
	SetTextAlign(hdc, TA_LEFT | TA_BOTTOM);
    SetTextColor(hdc, GetSkinRGB(SKIN_COLOR_LIST_ITEM_TEXT));
		//rect.bottom=rect.bottom+SCALE(DEFAULT_ITEM_HEIGHT)+SCALE(HEADER_HEIGHT);
		//int baseline=rect.bottom-SCALE(DEFAULT_ITEM_HEIGHT-ITEM_FONT_SIZE);
		//rect.top=rect.top+SCALE(DEFAULT_ITEM_HEIGHT)+SCALE(HEADER_HEIGHT)/2;
	// 4/22 
	int height=DrawText( hdc,value, -1, &rect, DT_WORDBREAK | DT_CALCRECT );
	if (height>MAINLIST_FONT_SIZE) //More than 1 line, needs to be placed further up
		rect.top=rect.top+SCALE(DEFAULT_ITEM_HEIGHT)+SCALE(HEADER_HEIGHT)/2;
	else
		rect.top=rect.top+SCALE(DEFAULT_ITEM_HEIGHT)+SCALE(HEADER_HEIGHT);
				// int baseline= rect.bottom
				//	- SCALE(DEFAULT_ITEM_HEIGHT - ITEM_FONT_SIZE) / 2;
		 
			
			//if (0 == _tcslen(value)) 
			//{
			//	ExtTextOut(hdc, rect.right - SCALE(LIST_ITEM_INDENT), baseline,
			//		ETO_CLIPPED, &rect, SZ_AUTO, 4, NULL);
			//}
			//else 
			//{
			//	ExtTextOut(hdc, rect.right - SCALE(LIST_ITEM_INDENT), baseline,
			//		ETO_CLIPPED, &rect, value, _tcslen(value), NULL);
			//}
				//InvalidateRect(0,&rect,true);
			//MessageBox(0,L"DrawValue",value,0);
	// 4/22/10 
	DrawText(hdc,value,_tcslen(value),//&rect,DT_WORDBREAK | DT_CALCRECT |DT_END_ELLIPSIS|DT_LEFT|DT_BOTTOM);
	&rect, DT_LEFT |DT_WORDBREAK| DT_NOCLIP); 

		//	rect.left=rect.right-10;
		//DrawText( hdc,L"v", _tcslen(L"v"), &rect, DT_END_ELLIPSIS );
		//int nIconWidth = SCALE(MENU_BAR_ICON_WIDTH);
		//int nHeaderHeight = SCALE(SKIN_HEADER_HEIGHT);
		//int nYOffset = SCALE(SKIN_HEADER_Y_OFFSET);
		//StretchBlt(hdc, 
		//		rHeader.right - nIconWidth, rHeader.top,
		//		nIconWidth, nHeaderHeight,
		//		hdcSkin, 
		//		nIconWidth * 4, nYOffset, 
		//		nIconWidth, nHeaderHeight,
		//		SRCCOPY);
    SelectObject(hdc, hfOld);
}*/
/*5/5/10 not neccessary
int categoryFiller(TCHAR options[MAX_OPTIONS][MAX_LOADSTRING], TCHAR * value) {
	HRESULT hr = E_FAIL;
	CEOIDINFOEX info = {0};

	CEGUID guid = {0};
	CEOID oid = 0;
	HANDLE hdb = NULL;

	int option_index = 0;

			//TODO ALLELIMO SUBITO: 
			// Default choice is AUTO [Favorites]
			//StringCchPrintf(options[option_index++], MAX_LOADSTRING, TEXT("%s [%s]"),
			//   SZ_AUTO, pSettings->favorites_default);

	// Read Database
//  CeMountDBVolEx(&guid, DB_VOL_FN, NULL, OPEN_EXISTING);
  // hdb = CeOpenDatabaseInSession(NULL, &guid, &oid, CATEGORY_DB_NAME,
	//   NULL, CEDB_AUTOINCREMENT, NULL);

//   CBR(hdb != INVALID_HANDLE_VALUE);
//
//   long lType = 0;
//   short iKey = 0;
//
//   CEPROPVAL * pRecord = NULL;
//   DWORD  dwBufSize = 0;
//   WORD   wNumProps;
//   for (WORD iRec = 0; iRec < MAX_OPTIONS; iRec++) {
//	   oid = CeReadRecordPropsEx(hdb, CEDB_ALLOWREALLOC, &wNumProps, NULL,
//		   (LPBYTE *)&pRecord, &dwBufSize, NULL);
//	   if (!oid)
//		   break;
//
//	  // for (WORD i = 0; i < wNumProps; i++) {
//	//	   switch(pRecord[i].propid) {
//	//case PROPID_CAT_NAME:
//	//	StringCchCopy(options[option_index++], MAX_LOADSTRING, pRecord[i].val.lpwstr);
//	//	break;
//	//	   }
//	//   }
//   }
//	
//Error:
//							   LocalFree(pRecord);
//							   CloseHandle(hdb);

							   return option_index;
}

int priorityFiller(TCHAR options[MAX_OPTIONS][MAX_LOADSTRING], TCHAR * value) {
	int index = 0;
	//ajige 4/19/10
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Low")); 
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Normal"));
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("High"));
	return index;
}

int statusFiller(TCHAR options[MAX_OPTIONS][MAX_LOADSTRING], TCHAR * value) {
	int index = 0;
	//ajige 4/19/10
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Free"));
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Tentative"));
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Busy"));  
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Out of Office"));  
	return index;
}

int sensitivityFiller(TCHAR options[MAX_OPTIONS][MAX_LOADSTRING], TCHAR * value) {
	int index = 0;
	//ajige 4/19/10
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Normal"));
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Personal"));
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Private"));  
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Confidential"));
	return index;
}

int attendeeFiller(TCHAR options[MAX_OPTIONS][MAX_LOADSTRING], TCHAR * value) {
	int index = 0;
	//ajige 4/19/10
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Attendee1"));
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Attendee2"));
	StringCchCopy(options[index++], MAX_LOADSTRING, TEXT("Attendee3"));  
	return index;
}
*/